2009-02-04 42 views
2

我的應用程序正在處理IList的。不同用戶定義類型的IList。我在想,我可以使用反射來查看IList包含的對象類型,然後創建該類型的新實例並隨後將其添加到IList本身?動態創建IList類型的新實例

所以在任何一個時間我可能會處理

IList<Customer> l; 

,我想爲客戶創造的新實例

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

,然後添加到列表中

l.Add(c); 

顯然,在運行時動態地做這件事是問題的關鍵。希望有人能給我一些指點。謝謝brendan

+0

小費,你應該說出你的郎我猜它的C#,但它應該是在有一些地方.... – Peter 2009-02-04 13:24:12

+0

是的,我只是意識到,查看自己的問題時,感謝 – user48408 2009-02-04 13:27:05

回答

4

試試這個:

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); 
    } 
0

這裏的一個大問題是:如果你不知道類型,你怎麼知道如何製作一個新的?並非世界上的每個類型都有一個構造函數,它接受一個int和一個字符串。

0

對不起,我應該提到,我將要處理的對象的集合將有一個構造函數接受一個int和一個字符串。

2

如果你可以使用一個無參數的構造函數,之後設置的屬性,那麼你可以讓你的方法一般,像: -

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和字符串屬性的基礎。如果需要,您可以使用接口而不是基類。

+0

此代碼不能正常工作,並沒有什麼類似的實現這種效果。 – 2009-02-04 13:38:34

+0

糟糕,你是正確的,已經相應地編輯了這篇文章。謝謝 – 2009-02-04 13:50:35

1

您可以使用Activator.CreateInstance方法通過類型名稱(字符串)或System.Type的實例爲類調用構造函數。

1

我想你應該改變你的設計。您可以使用abstract factory pattern。使用反射會降低性能。

這裏是工廠的代碼。

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(); 
} 
1

你可以使用Type.GetGenericArguments方法返回泛型類型的IList的類型參數< T>。然後調用適當的構造函數。

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" }); 
0

最好的方式來獲得的IList的類型是看看屬性類型索引的!

var collectionType = targetList.GetType().GetProperty("Item").PropertyType; 
var constructor = collectionType.GetConstructor(Type.EmptyTypes); 
var newInstance = constructor.Invoke(null);