سؤال

طلبي هو تجهيز IList هو.ILists من مختلف الأنواع المعرفة من قبل المستخدم.أنا أفكر يمكن استخدام التفكير لمعرفة ما هو نوع من كائن IList يحتوي ثم إنشاء مثيل جديد من هذا النوع في وقت لاحق إضافة إلى أن IList نفسها ؟

لذلك في أي وقت من الأوقات قد تكون المعالجة

IList<Customer> l;

وأود أن إنشاء مثيل جديد من العملاء

Customer c = new Customer(0, "None")

ثم إضافة ذلك إلى قائمة

l.Add(c);

ومن الواضح أن القيام بذلك بشكل حيوي في وقت التشغيل هو جوهر المشكلة.آمل شخص يمكن أن تعطيني بعض المؤشرات.شكرا بريندان

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

المحلول

جرب هذا:

    public static void AddNewElement<T>(IList<T> l, int i, string s)
    {
        T obj = (T)Activator.CreateInstance(typeof(T), new object[] { i, s });
        l.Add(obj);
    }

الاستخدام:

    IList<Customer> l = new List<Customer>();
    l.Add(new Customer(1,"Hi there ..."));

    AddNewElement(l, 0, "None");

(تحرير):

حاول هذا:

    public static void AddNewElement2(IList l, int i, string s)
    {
        if (l == null || l.Count == 0)
            throw new ArgumentNullException();
        object obj = Activator.CreateInstance(l[0].GetType(), new object[] { i, s });
        l.Add(obj);
    }

نصائح أخرى

إذا يمكنك استخدام منشئ parameterless وتعيين الخصائص بعد ذلك ثم يمكنك جعل طريقتك عام، شيء من هذا القبيل: -

    void Process<T>(IList<T> list, int x, string y) where T : MyBase, new()
    {
        T t = new T();
        t.X = x;
        t.Y = y;
        list.Add(t);
    }

وأين MyBase هو قاعدة للفئات الخاصة بك التي تعرض int و سلسلة خصائص. يمكنك استخدام واجهة بدلا من الفئة الأساسية إذا كنت تريد.

يمكنك استخدام الأسلوب Activator.CreateInstance لاستدعاء منشئ لل فئة عن طريق اسم نوعه (كسلسلة) أو مثيل System.Type.

وأعتقد أن عليك أن تغيير التصميم الخاص بك. يمكنك استخدام مجردة نمط مصنع . باستخدام الانعكاس سوف تحط في الأداء.

وهنا هو رمز للمصنع.

public abstract class MyStore {
    public abstract string Name { get; }
    public abstract void AddItem(int id, string name);
}

ويمكنك النظر في استخدام واجهة إذا فئة مجردة لديه أي رمز.

وبعد ذلك إنشاء مخزن العملاء.

public class CustomerStore : MyStore, IEnumerable<Customer> {
    List<Customer> list = new List<Customer>();

    public override string Name { get { return "Customer Store"; } }
    public override void AddItem(int id, string name) {
        list.Add(new Customer(id, name));
    }
    public IEnumerator<Customer> GetEnumerator() {
        return list.GetEnumerator();
    }
}
<ع> الاستخدام

foreach (MyStore store in List<MyStore>)
    store.AddItem(0, "None");

إذا كنت ترغب في النظر في نوع من متجر، واستخدام

switch (store.Name) {
case "Customer Store":
    SomeMethod((CustomerStore)store);
    break;
default:
    throw new WhatEverException();
}

هل يمكن استخدام الأسلوب Type.GetGenericArguments للعودة الحجة نوع من نوع عام IList . ثم استدعاء منشئ المناسب.

  Type T = l.GetType ( ).GetGenericArguments ( ) [ 0 ];
  ConstructorInfo ctor = T.GetConstructor (
    new Type [ 2 ] { typeof ( int ), typeof ( string ) } );
  System.Diagnostics.Debug.Assert ( ctor != null );
  object instance = ctor.Invoke (
    new object [ 2 ] { 0, "None" } );

نعم أنا آسف يتعين عليه أن يذكر أن مجموعة من الكائنات سوف أكون معالجة سيكون له منشئ يقبل عدد صحيح وسلسلة.

والمشكلة الكبرى هنا هي: إذا كنت لا تعرف نوع، كيف يمكنك أن تعرف كيفية جعل واحدة جديدة؟ ليس كل نوع في العالم لديه منشئ التي تأخذ int و سلسلة.

أفضل طريقة للحصول على نوع من IList هو نظرة على نوع العقار من مفهرس!

var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top