2009-02-03 33 views
6

Trong mã của tôi có một số chuỗi được sử dụng làm khóa để truy cập tài nguyên. Các khóa này có định dạng cụ thể, ví dụ:Kiểm tra định dạng chuỗi tại thời gian biên dịch trong C#

string key = "ABC123"; 

Hiện tại, tất cả các khóa này được lưu trữ dưới dạng chuỗi nhưng tôi muốn làm cho mọi thứ trở nên mạnh mẽ hơn và an toàn hơn. Lý tưởng nhất, tôi muốn kiểm tra các chuỗi có định dạng chính xác tại thời gian biên dịch.

Giai đoạn tiếp theo là tạo lớp ResourceKey được khởi tạo từ chuỗi. Sau đó, tôi có thể kiểm tra định dạng của chuỗi khi chạy, ví dụ:

ResourceKey key = "ABC123"; 

nơi resourcekey được định nghĩa là:

using System.Diagnostics; 
using System.Text.RegularExpressions; 

class ResourceKey 
{ 
    public string Key { get; set; } 

    public static implicit operator ResourceKey (string s) 
    { 
     Debug.Assert(Regex.IsMatch(s, @"^[A-Z]{3}[0-9]{3}$")); 
     return new ResourceKey() { Key = s }; 
    } 
} 

Những gì tôi thực sự muốn làm là phải có một loại thời gian biên dịch khẳng định để chương trình thất bại trong việc xây dựng nếu có ai cố gắng sử dụng một khóa không hợp lệ. ví dụ.

ResourceKey k1 = "ABC123"; // compiles 
ResourceKey k2 = "DEF456"; // compiles 
ResourceKey k3 = "hello world"; // error at compile time 

Có cách nào để đạt được điều này không?

Cảm ơn

Trả lời

8

Bạn có thể kiểm tra giá trị bằng thử nghiệm đơn vị. Một trong những đồng nghiệp của tôi đã phải làm một cái gì đó tương tự như vậy trong một dự án mà chúng tôi cần đảm bảo rằng tất cả các lớp trong một không gian tên nhất định có các thuộc tính nhất định áp dụng cho chúng.

Chạy thử nghiệm đơn vị bằng công cụ xây dựng của bạn (bạn làm điều đó dù sao phải không? :) hoặc như một phần của bản dựng tích hợp. Điều này sẽ giữ cho nguồn của bạn sạch hơn cũng như bạn sẽ không phải giới thiệu mã mà không xác nhận.

+0

Tôi đồng ý về vấn đề này, tôi cũng gợi ý kiểm tra http://www.postsharp.org/ để đảm bảo/sau khi lô-gic – kentaromiura

+0

Ý tưởng hay - nhưng thật không may các phím này được truyền đi trong hàng chục nghìn dòng mã cũ - phần lớn không được kiểm tra bằng đơn vị. Chúng tôi sẽ đến đó! – roomaroo

+0

Xin lỗi vì đã nghe về điều đó! –

1

Bạn có thực sự muốn các khóa này được mã hóa cứng vào ứng dụng của mình không? Nó sẽ không được tốt hơn để có chúng trong một tập tin cấu hình? Sau đó, nếu có bất kỳ vấn đề sau khi biên dịch, nó chỉ đơn giản là một vấn đề cấu hình thời gian chạy.

+0

Một ưu điểm khác của một kho lưu trữ dựa trên XML cho các tên khóa sẽ là tệp luôn có thể được xác nhận hợp lệ đối với một lược đồ. – Cerebrus

+0

Các khóa là tham chiếu đến các mục nhập trong một tệp XML. Nếu tất cả các cài đặt của bạn nằm trong tệp cấu hình, bạn vẫn cần một cách để chỉ định cài đặt nào cần xem. – roomaroo

+0

Vì nó xuất hiện như thể đây là những khóa cho một tệp tài nguyên, đặt chúng vào một cấu hình có nghĩa là bạn sẽ chỉ cần một bộ chuỗi mã hóa cứng khác để có được những giá trị đó. Tại một số điểm bạn phải hardcode một chuỗi khóa vào mã hoặc cung cấp nó như là đầu vào mà sẽ không được thực tế ở đây. –

2

Tôi tin rằng tôi sẽ thêm lớp Cài đặt và lưu trữ chúng ở đó thay vì tạo loại mới. Lớp Cài đặt có thể được hỗ trợ bởi một tệp cấu hình ứng dụng sẽ làm cho chúng dễ thay đổi hơn thông qua các thay đổi tệp cấu hình nếu cần. Tuy nhiên, nếu bạn không chỉ định chúng trong tệp cấu hình, nó sẽ sử dụng các giá trị bạn đặt làm mặc định.

Tôi cũng sẽ đi tuyến kiểm tra đơn vị. Bạn sẽ cần phải sử dụng thuộc tính InternalsVisibleTo trong file Assembly.cs của bạn vì tôi không nghĩ rằng các thiết lập có thể được sử dụng bên ngoài dự án nếu bạn không.

+0

+1 cho tệp Cài đặt và InternalsVisibleTo –

1

AdamRalph có một điểm nhưng điểm truy cập cũng làm việc, nếu bạn nhận được nó ngay tại thời gian biên dịch, bạn sẽ không bao giờ có vấn đề cấu hình thời gian chạy (giả định các giá trị đúng không thể thay đổi)

Bên ngoài đó, Khả năng biên dịch thời gian của C# là tuyệt đối Junk. Của họ là bên cạnh không có gì có thể được thực hiện tại thời gian biên dịch. Điều tốt nhất tôi biết là mệnh đề mẫu where. Nếu tôi phải đoán, tôi muốn nói rằng đây là một sự lựa chọn thiết kế có chủ đích của Anders Hejlsberg vì nó có vẻ phù hợp với phần còn lại của ngôn ngữ

Điểm của Andrew Hare về unittests + reflection là tốt như tôi muốn chờ đợi. Một nhân viên của tôi sử dụng điều đó để kiểm tra xem bất kỳ lớp nào có thể được sử dụng trong một trường hợp cụ thể đã thực hiện đúng một số giao thức.

1

Nếu các phím được đặt tên theo các quy tắc tương tự như C# định danh, hoặc thậm chí nhiều hạn chế, và được biết đến và hữu hạn, bạn có thể sử dụng một enum:

public enum ResourceKeys 
{ 
    ABC123, 
    DEF456 
} 
Các vấn đề liên quan