2012-01-03 15 views
6

Tôi có phần cấu hình tùy chỉnh đã đăng ký trong app/web.config, hãy gọi nó là MySection. Tôi có một phần tử ElementCollection bên trong phần, được gọi là MyElements. Bên trong bộ sưu tập phần tử Tôi muốn có các phần tử được đại diện bởi các lớp khác nhau - ý tưởng là đây là các lớp tương tự với một số thuộc tính phổ biến và một số đặc trưng cho cá thể.Cấu hình tùy chỉnh .NET - Tôi có thể thu thập các phần tử với các phần tử không đồng nhất không?

Dưới đây là một số ví dụ cấu hình xml:

<MySection> 
    <MyElements> 
    <Element1 name="someProp1" value="someValue" /> 
    <Element2 name="someProp2" format="{0}{1}" /> 
    </MyElements> 
</MySection> 

Trong ví dụ đơn giản của tôi, tất cả các yếu tố này phải có một 'tên' bất động sản, một số sẽ có còn là một 'giá trị' bất động sản, và người kia là 'định dạng' bất động sản. Ở đây, tôi muốn Element1Element2 được thể hiện trong thời gian chạy .NET bởi hai lớp khác nhau có lớp cơ sở chung xác định thuộc tính 'tên'.

Theo như tôi đã đào sâu vào cấu hình .NET, tôi có ấn tượng rằng một bộ sưu tập phần tử (như 'MyElements' ở đây) nên chứa các phần tử đồng nhất (chỉ có một loại). Vì vậy, nó có thể có thể đạt được những gì tôi muốn - làm cho nó chứa các yếu tố của các lớp khác nhau. Ý tưởng là để tránh cả hai có nhiều hơn một bộ sưu tập phần tử cho các loại phần tử khác nhau và không viết tất cả các thuộc tính lặp lại cho mọi triển khai ConfigurationElement tùy chỉnh.

Trả lời

8

Bạn có thể thực hiện điều này bằng cách ghi đè phương thức OnDeserializeUnrecognizedElement trong lớp ElementCollection của bạn và tạo các biểu diễn của Element1 và Element2 bằng cách bật tên thẻ cho ex. Tuy nhiên, các yếu tố con AFAIR nên được bắt nguồn từ tổ tiên chung dù sao đi nữa, nếu không nó sẽ là quá nhiều rắc rối.

Xác định bộ sưu tập như:

public class MyElementCollection : ConfigurationElementCollection 
{ 
    const string ELEMENT1 = "Element1"; 
    const string ELEMENT2 = "Element2"; 

    protected override ConfigurationElement CreateNewElement() 
    { 
     return new MyElement (this); 
    } 

    protected override object GetElementKey (ConfigurationElement element) 
    { 
     return ((MyElement)element).Key; 
    } 

    // This method called when framework sees unknown element tag 
    // inside the collection. You can choose to handle it yourself 
    // and return true, or return false to invoke default action 
    // (exception will be thrown). 
    protected override bool OnDeserializeUnrecognizedElement (string elementName, XmlReader reader) 
    { 
     if (elementName == ELEMENT1 || elementName == ELEMENT2 { 
      var myElement = new MyElement (this); 

      switch (elementName) { 
      case ELEMENT1: 
       myElement.Type = MyElementType.Element1; 
       break; 
      case ELEMENT2: 
       myElement.Type = MyElementType.Element2; 
       break; 
      } 

      myElement.DeserializeElementForConfig (reader, false); 
      BaseAdd (myElement); 

      return true; 
     } 

     return false; 
    } 
} 

Và phần tử con:

public enum MyElementType 
{ 
    Element1, 
    Element2, 
} 

public class MyElement : ConfigurationElement 
{ 
    const string NAME = "name"; 
    const string VALUE = "value"; 
    const string FORMAT = "format"; 

    // keys should be unique, current collection count will do 
    // the trick without introducing artificial keys 
    public MyElement (ConfigurationElementCollection collection) 
    { 
     Key = collection.Count; 
    } 

    // note that this is not ConfigurationProperty 
    public int Key { get; private set; } 

    // note that this is not ConfigurationProperty 
    public MyElementType Type { get; set; } 

    [ConfigurationProperty(NAME)] 
    public string Name { 
     get { return (string)this [NAME]; } 
    } 

    [ConfigurationProperty(VALUE)] 
    public string Value { 
     get { return (string)this [VALUE]; } 
    } 

    [ConfigurationProperty(FORMAT)] 
    public string Format { 
     get { return (string)this [FORMAT]; } 
    } 

    // This is called when framework needs a copy of the element, 
    // but it knows only about properties tagged with ConfigurationProperty. 
    // We override this to copy our Key and Type, otherwise they will 
    // have default values. 
    protected override void Reset (ConfigurationElement parentElement) 
    { 
     base.Reset (parentElement); 

     var myElement = (MyElement)parentElement; 
     Key = myElement.Key; 
     Type = myElement.Type; 
    } 

    // original ConfigurationElement have this protected, 
    // redeclaring as protected internal to call it from collection class 
    protected internal void DeserializeElementForConfig (XmlReader reader, bool serializeCollectionKey) 
    { 
     DeserializeElement (reader, serializeCollectionKey); 
    } 
} 
+0

Cảm ơn bạn đã trả lời của bạn. Thật vậy, một tổ tiên chung là những gì tôi có nghĩa là để sử dụng anyway. Ít nhất, tôi đang cố gắng tái sử dụng các thuộc tính chung của các phần tử tương tự, do đó tổ tiên chung có thể lưu trữ chúng và cũng làm giảm mã cho các phần tử cụ thể :) –

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