سؤال

هل من الممكن أن يكون لديك مجموعة عناصر مع عدد من العناصر المختلفة حسب النوع ، على سبيل المثال.:

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

لدي جميع الفئات المطلوبة لمثل هذا الحل:

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

ولكن عندما أبدأ طلبي أنا الحصول على خطأ يمكن التنبؤ به المقبل:

السمة غير المعترف بها 'النوع 1 سبيسيفيكبروب'.

لأن Type1SpecificProp يتم تعريفه في MyType1 لا MyElement, ، خاصة إذا MyCollection لديه الطريقة التالية:

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

أي.إرجاع الطبقة الأساسية وبالتالي OnDeserializeUnrecognizedAttribute() في الطفل المصنف لم يتم استدعاؤه أبدا.

لذا فإن السؤال هو:كيفية السماح لفصول الأطفال بحل العناصر غير المعروفة بأنفسهم?

هل كانت مفيدة؟

المحلول 2

Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfigurationElementCollection<T> من إنتليب 5 قم بهذه المهمة كسحر.

نصائح أخرى

نظرت في هذا أيضا. PolymorphicConfigurationElementCollection<T> يبدو مهملا.تحرير:انها ليست ، انظر تعليق 'أباتيشيف' أدناه ، كنت مجرد ربط نسخة قديمة.

كان حل جناح الراحة واعدا ولكنه تطلب للأسف استدعاء الأساليب الداخلية الموجودة في مساحة اسم أخرى.في حين أن هذا ممكن من خلال التفكير ، إلا أنه لن يتلقى أسعارا لترميز الجمال في هذه الحالة.

لقد حفرت في المصدر مع التفكير أيضا وتوصلت إلى الحل التالي:

[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; }
    }
}

مطلوب تجاوز نوع المجموعة ، حتى إذا تم تحديد ذلك عبر السمة في الأعلى.عندما لا يتم تجاوز الفئة الأساسية 'كولكتيونتيب لا يزال يشير إلى' أدريموفكليرماب 'الذي لن يؤدي إلى تشغيل المطلوبة' كريتينيوليمنت(سلسلة إليمنتنام) 'وظيفة ولكن انها متغير بارامترليس'كريتينميمنت ()'.لنفس السبب يجب أن تعود وظيفة إيسيليمنتنام الكتابة صحيح.

لاحظ أنني أنشأت إليمنتباسيكونفيغ وهي الفئة الأساسية لكل من ميتيب 1 كونفيغ و ميتيب 2 كونفيغ التي يمكنك تحديد بعض السمات المشتركة.

مثيل من نوع معين (MyType1 و MyType2) يحتاج إلى إنشاء من أجل الطبقات الفرعية لحل عناصر غير معروفة أو سمات من تلقاء نفسها.

منذ CreateNewElement لا تعطي الطريقة أي معلومات عن سمات العنصر ، وهذا ليس المكان الذي يمكن أن يحدث فيه إنشاء مثيل لنوع معين.

بعد بعض الحفر عبر العاكس ، يأتي المرء إلى مكدس الاستدعاءات الجزئي التالي:

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

ال OnDeserializeUnrecognizedElement يمكن تجاوز الطريقة في MyCollection فئة من أجل إنشاء مثيل نوع معين.بدلا من استخدام المعلمات CallCreateNewElement الطريقة ، استخدم واحدة جديدة تتلقى XmlReader:

  1. قراءة السمة type (ضمان وجودها وصلاحيتها).
  2. إنشاء عنصر جديد من النوع المحدد.
  3. اتصل internal virtual void AssociateContext( BaseConfigurationRecord configRecord ) طريقة System.Configuration.ConfigurationElement على العنصر.
  4. اتصل internal void CallInit() طريقة System.Configuration.ConfigurationElement على العنصر.
  5. إرجاع العنصر المعد.

راجع للشغل ، إذا لم يكن هناك الكثير من عناصر المجموعة المختلفة ، ففكر في استخدام شيء مثل:

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

بهذه الطريقة يمكنك تجنب صب العناصر من MyCollection إلى نوع معين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top