9

Có thể có một CollectionElementCollection với một số khác nhau theo loại CollectionElements, ví dụ:ConfigurationElementCollection với một số ConfigurationElements loại khác nhau

<collection> 
    <add type="MyType1, MyLib" Type1SpecificProp="1" /> 
    <add type="MyType2, MyLib" Type2SpecificProp="2" /> 
</collection 

tôi có đầy đủ các lớp học cần thiết cho giải pháp như:

class MyCollection : ConfigurationElementCollection { } 
class MyElement : ConfigurationElement { } 
class MyType1 : MyElement { } 
class MyType2 : MyElement { } 
... 
etc 

nhưng khi tôi khởi động ứng dụng, tôi nhận được lỗi dự đoán tiếp theo:

Unrecognized attribute 'Type1SpecificProp'.

Type1SpecificProp được định nghĩa trong MyType1 không MyElement, đặc biệt là nếu MyCollection có phương pháp tiếp theo:

protected override ConfigurationElement CreateNewElement() 
{ 
    return new MyElement(); // but I want instantiate not the base class but by a type given 
} 

ví dụ: lợi nhuận lớp cơ sở như vậy OnDeserializeUnrecognizedAttribute() trong con xếp vào loại không bao giờ được gọi.

Vì vậy, câu hỏi đặt ra là: làm thế nào để cho các lớp con giải quyết các yếu tố không xác định bằng chính chúng?

Trả lời

2

Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfigurationElementCollection<T> từ EntLib5 thực hiện công việc này như một sự quyến rũ.

+0

Tôi biết câu trả lời này đã được đăng cách đây một thời gian, nhưng bạn có thể đi sâu hơn một chút nếu bạn đánh dấu câu trả lời này là câu trả lời được chấp nhận không? – goric

+0

@goric: Bạn cần kế thừa và ghi đè 'RetrieveConfigurationElementType' thành loại thay thế trong thời gian chạy. Đồng thời xem [NameTypeConfigurationElementCollection] (http://msdn.microsoft.com/en-us/library/ee939739%28PandP.50%29.aspx) – abatishchev

1

Ví dụ về loại cụ thể (MyType1MyType2) cần được tạo để các lớp con tự giải quyết các phần tử hoặc thuộc tính không xác định.

Vì phương thức CreateNewElement không cung cấp bất kỳ thông tin nào về thuộc tính của phần tử, đó không phải là nơi diễn ra sự kiện loại cụ thể.

Sau khi một số digging qua suy nghi, ai đến sau một phần cuộc gọi stack:

VariantCollection.MyCollection.CreateNewElement() 
System.Configuration.ConfigurationElementCollection.CallCreateNewElement() 
System.Configuration.ConfigurationElementCollection.OnDeserializeUnrecognizedElement(string elementName, XmlReader reader) 

Phương pháp OnDeserializeUnrecognizedElement có thể được overriden trong MyCollection lớp nhằm tạo Ví dụ loại hình cụ thể. Thay vì sử dụng các phương pháp parameterless CallCreateNewElement, sử dụng một mới nhận XmlReader: thuộc tính

  1. đọc type (đảm bảo sự tồn tại và giá trị của nó).
  2. Tạo thành phần mới của loại được chỉ định.
  3. Gọi internal virtual void AssociateContext(BaseConfigurationRecord configRecord) phương thức System.Configuration.ConfigurationElement trên phần tử.
  4. Gọi internal void CallInit() phương thức System.Configuration.ConfigurationElement trên phần tử.
  5. Trả lại phần tử đã chuẩn bị.

BTW, nếu có sẽ không có quá nhiều yếu tố thu khác nhau, xem xét sử dụng một cái gì đó như:

<myType1Collection> 
    <add Type1SpecificProp="1" /> 
</myType1Collection> 
<myType2Collection> 
    <add Type2SpecificProp="2" /> 
</myType2Collection> 

Bằng cách đó bạn có thể tránh được đúc các mục từ MyCollection để loại cụ thể.

11

Tôi cũng đã xem xét điều này. PolymorphicConfigurationElementCollection<T>seems deprecated. Chỉnh sửa: không, hãy xem nhận xét của 'abatishchev' bên dưới, tôi vừa mới liên kết một phiên bản cũ.

Giải pháp của Rest Wing là hứa hẹn nhưng tiếc là yêu cầu phải gọi các phương thức nội bộ nằm trong một không gian tên khác. Trong khi điều này là có thể thông qua phản ánh nó sẽ không nhận được giá cho mã hóa vẻ đẹp trong trường hợp này.

tôi đào vào nguồn với Reflection quá và đã đưa ra các giải pháp sau đây:

[ConfigurationCollection(typeof(ElementBaseConfig), CollectionType=ConfigurationElementCollectionType.BasicMap)] 
public class MyTypesConfigCollection : ConfigurationElementCollection 
{ 
    protected override ConfigurationElement CreateNewElement() 
    { 
     // Not used but function must be defined 
     return null; 
    } 

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

    protected override ConfigurationElement CreateNewElement(string elementName) 
    { 
     switch (elementName) 
     { 
      case "mytype1": 
       return new MyType1Config(); 

      case "mytype2": 
       return new MyType2Config(); 

      default: 
       throw new ConfigurationErrorsException(
        string.Format("Unrecognized element '{0}'.", elementName)); 
     } 
    } 

    protected override bool IsElementName(string elementName) 
    { 
     // Required to be true 
     return true; 
    } 

    public override ConfigurationElementCollectionType CollectionType 
    { 
     get { return ConfigurationElementCollectionType.BasicMap; } 
    } 
} 

Các override của CollectionType là cần thiết, thậm chí nếu điều này đã được xác định thông qua các thuộc tính trong đầu. Khi không ghi đè lớp cơ sở 'CollectionType vẫn đề cập đến' AddRemoveClearMap 'mà sẽ không kích hoạt chức năng' CreateNewElement (string elementName) 'bắt buộc nhưng nó là biến thể parameterless' CreateNemElement() '. Vì lý do tương tự, hàm IsElementName bị ghi đè sẽ trả về true.

Lưu ý rằng tôi đã tạo một ElementBaseConfig là lớp cơ sở của cả MyType1Config và MyType2Config, trong đó bạn có thể xác định một số thuộc tính được chia sẻ.

+2

Bạn đã liên kết ver. 3.1, [đây là mới đây] (http://msdn.microsoft.com/en-us/library/bb750549%28PandP.50%29.aspx) và không lỗi thời – abatishchev

+0

Bạn đã đúng, đã thay đổi câu trả lời của tôi để phản ánh điều này. Cảm ơn vì đã chú ý. – user1088858

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