2008-10-24 27 views
9

class<T> gibi jenerik kullanan bir sınıfın çalışma zamanı örneklerinde, daha önce T türünün ne olacağını bilmeden, ben böyle bir şey yapmak isterim:Generics'i dinamik olarak kullanmak imkansız mı?

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     lists.Add(type, new List<type>()); /* this new List<type>() doesn't work */ 
    } 

    return lists; 
} 

... 't. Bence, C# 'de genel bir parantez içinde bir tip değişkeni yazmak mümkün değil. Bunu yapmanın başka bir yolu var mı?

+0

Çalışma zamanında güvenli bir Genel Nesne oluşturmak için neden bir neden verebilir misiniz? –

+0

Birkaç kez yaptım, özellikle Protokol Tamponları taşırken. –

+0

İşimde buradaki kalıcılık çerçevesine bir bağdaştırıcı yapıyorum ve sınıfların çalışmalarını gerçekleştirmek için bu bilgilere ihtiyacı var. –

cevap

17

Böyle bunu yapamaz - jenerik noktası çoğunlukla derleme zamanı tip emniyet - ama yansıması ile yapabilirsiniz: ne sıklıkta sen bağlı

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     Type genericList = typeof(List<>).MakeGenericType(type); 
     lists.Add(type, Activator.CreateInstance(genericList)); 
    } 

    return lists; 
} 
+0

tekrar teşekkürler Jon. CreateInstance, boş bir kurucu gerektirir mi? Anlamadım, aslında ona bir parametre girmem gerekiyor. –

+0

Bir kurucu gerektirir. Bir kurucu kullanmak istemiyorsanız, System.Runtime.Serialization derlemesinde FormatterServices.GetUninitializedObject() öğesini kullanabilirsiniz. –

+1

@Victor: Activator.CreateInstance'ın parametre aldığı aşırı yüklenmeler var veya Type.GetConstructor'ı kullanabilir ve sonra bunu çağırırsınız. Temel olarak, bir türden bir tür örneğine gitmenin birçok yolu vardır - birini seçin :) –

4

Activator.CreateInstance kullanarak bu yöntemi çağırmak yavaş olabilir. Başka bir seçenek de bunun gibi bir şey yapmaktır:

private Dictionary> delegates = new Dictionary>(); İlk olarak

public Dictionary<Type, object> GenerateLists(List<Type> types) 
    { 
     Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

     foreach (Type type in types) 
     { 
      if (!delegates.ContainsKey(type)) 
       delegates.Add(type, CreateListDelegate(type)); 
      lists.Add(type, delegates[type]()); 
     } 

     return lists; 
    } 

    private Func<object> CreateListDelegate(Type type) 
    { 
     MethodInfo createListMethod = GetType().GetMethod("CreateList"); 
     MethodInfo genericCreateListMethod = createListMethod.MakeGenericMethod(type); 
     return Delegate.CreateDelegate(typeof(Func<object>), this, genericCreateListMethod) as Func<object>; 
    } 

    public object CreateList<T>() 
    { 
     return new List<T>(); 
    } 

o liste oluşturur ve daha sonra bir sözlükte olduğu koyar jenerik yönteme bir temsilci oluştururuz çarptı. Sonraki her isabet üzerinde sadece bu tip için temsilci çağırırsınız.

Bu yardımcı olur umarız!

+0

Teşekkürler jonni, bu yöntemi sadece bir kez diyorum, aksi takdirde bir delege tutmak iyi bir seçenek olur. –

İlgili konular