2009-09-18 21 views
6

Có thể sử dụng các loại không thay đổi làm thuộc tính cấu hình với API cấu hình của .NET không?Các loại không thể thay đổi làm thuộc tính cấu hình

Hãy nói rằng tôi có một loại bất biến gọi là MyClass:

public class ImmutableClass 
{ 
    private readonly int value; 

    public ImmutableClass(int value) 
    { 
     this.value = value; 
    } 

    public int Value 
    { 
     get { return this.value; } 
    } 
} 

Tôi muốn sử dụng loại này như một thuộc tính cấu hình trong một ConfigurationSection:

public class MyConfigurationSection : ConfigurationSection 
{ 
    [ConfigurationProperty("foo")] 
    public ImmutableClass Foo 
    { 
     get { return (ImmutableClass)base["foo"]; } 
     set { base["foo"] = value; } 
    } 
} 

Khi tôi làm điều này, tôi có thể 's serialize và deserialize MyConfigurationSection vì nó ném ngoại lệ này:

System.Configurati on.ConfigurationErrorsException: Không thể chuyển đổi giá trị của tiêu chí 'thuộc tính' thành chuỗi. Lỗi là: Không thể tìm thấy trình chuyển đổi hỗ trợ chuyển đổi thành/từ chuỗi cho tiêu chí 'thuộc tính' của loại 'Tìm tiêu đề'.

Nếu tôi lấy ImmutableClass từ ConfigurationElement, tôi nhận được ngoại lệ này khi tôi cố gắng để serialize và deserialize phần cấu hình:

System.Reflection.TargetInvocationException: ngoại lệ đã được ném bởi mục tiêu của một invocation . ---> System.Reflection.TargetInvocationException: Ngoại lệ đã được ném bởi mục tiêu của một lời gọi. ---> System.MissingMethodException: Không có hàm tạo tham số nào được định nghĩa cho đối tượng này.

Tôi có toàn quyền kiểm soát ImmutableClass, vì vậy tôi có thể triển khai bất kỳ giao diện nào là cần thiết.

Có cách nào tôi có thể móc vào API cấu hình để ImmutableClass có thể được sử dụng theo cách này không?

Trả lời

1

Bạn có thể sử dụng một số TypeConverters để trợ giúp quá trình này (liên kết với System.Configurations.ConfigurationConverter).

Câu hỏi thực sự là tại sao bạn muốn gây cho mình nhiều rắc rối? Chỉ có một số lần tốt hơn để nằm lại và mang nó hơn là đưa ra một cuộc chiến. Một số phần của khung làm bực bội nếu bạn cố gắng thực hiện nó theo bất kỳ cách nào khác với cách cụ thể được đặt ra cho bạn ....

+0

+1. Cảm ơn, mà làm việc tốt. Tôi đồng ý rằng trong hầu hết các trường hợp, chỉ cần đi với dòng chảy sẽ dễ dàng hơn, và đó cũng là điều tôi thường làm, nhưng đây là trường hợp đặc biệt ... –

+0

Điều cần biết ... Tôi thực sự đang thử nghiệm với các loại bất biến và xaml tuần tự hóa. Tôi hy vọng các trình biến đổi kiểu sẽ làm việc cho tôi! – Will

4

Cá nhân tôi nghĩ bạn sẽ làm tốt hơn để tách dữ liệu trong cấu hình phần (mà dường như cần phải được thay đổi), và cách bạn thể hiện nó trong mô hình đối tượng của bạn. Không có gì ngăn bạn có hai biểu diễn - một phiên bản đơn giản (DTO/POCO) cho cấu hình và phiên bản tùy chỉnh của bạn (không thay đổi trong trường hợp này) để sử dụng thực trong ứng dụng của bạn.

+0

Tôi sẽ đồng ý trong hầu hết các trường hợp, và đó cũng là những gì tôi thường làm, nhưng đây là một trường hợp đặc biệt. –

0

Tôi sẽ từ bỏ lời nguyền đó vì ý tưởng bị nguyền rủa. Tất cả các trình xử lý phần cấu hình phải có một hàm tạo mặc định (không tham số). Đây không phải là trường hợp với đối tượng bất biến của bạn.

Giải pháp đơn giản nhất là đặt một mức trừu tượng khác giữa cấu hình và ứng dụng của bạn. Bạn có thể áp dụng mẫu nhà cung cấp cấu hình và có thể chuyển đổi các lớp có thể thay đổi "miễn phí cho tất cả" thành phần cấu hình thành các lớp không thể thay đổi được ứng dụng của bạn sử dụng.

Tôi phải nói rằng đây là cách sử dụng các phần cấu hình. Tôi biết rằng có một lựa chọn trở lại wright nhưng tôi chưa bao giờ sử dụng nó trước đây.

Mã này có thể trông giống như sau:

Việc xử lý cấu hình

public class SectionHandler : ConfigurationSection 
{ 
    [ConfigurationProperty("foo")] 
    public MyObject ConfigurationValue 
    { 
    get { return (MyObject) this["foo"]; } 
    } 
} 

Sau khi bạn đã nhận được giá trị cấu hình ra khỏi các tập tin XML và vào một đối tượng sử dụng các mô hình cung cấp cấu hình để tiêu thụ cấu hình trong ứng dụng của bạn.

Nhà cung cấp cấu hình sẽ có thể trông giống như thế này:

public MyConfigurationProvider : IMyconfigurationProvider 
{ 

    public MyImmutabble ConfigurationValue 
    { 
    get 
    { 
     var configurationvalue = (MyObject) ConfigurationManager.GetSection("mySection"); 
     return new MyImmutable(configurationvalue.ConfigurationValue); 
    } 
    } 
} 

Đây là cách tôi làm điều đó và nó đã phục vụ tôi cho đến nay.

Hy vọng điều đó sẽ hữu ích.

+0

Trong trường hợp bình thường, tôi đồng ý với bạn hoàn toàn, và đó cũng là cách tiếp cận bình thường của tôi, nhưng đây là một trường hợp đặc biệt. Tôi chỉ làm cho nó hoạt động với TypeConverts như đề xuất của Will, và điều đó làm việc tốt, vì vậy yêu cầu ban đầu của bạn là không đúng sự thật. –

Các vấn đề liên quan