2008-11-05 14 views
140

Başlık, bir tür belirsizdir. Ne bilmek istiyorum bu mümkün olup olmadığını geçerli: AçıkçasıAnlık Sistemin Geçişi Bir Genel Sınıf için Tip Parametresi Olarak Yazma

string typeName = <read type name from somwhere>; 
Type myType = Type.GetType(typeName); 

MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>(); 

, MyGenericClass olarak tarif edilir: Şu anda

public class MyGenericClass<T> 

, derleyici 'tür veya ad alanı 'myType' olamayacağını şikayet "Bunu yapmak için bir yol var.

+0

Jenerik! = Şablonları. Tüm jenerik tip değişkenleri, çalışma zamanında değil, derleme zamanında çözülür. Bu, 'dinamik' tip 4.0'ın faydalı olabileceği durumlardan biridir. – Will

+1

@Will - hangi şekilde? Generics ile kullanıldığında, geçerli CTP altında temelde versiyonlarını çağırıyorsunuz (bir hileyi kaçırmadıkça ...) –

+0

@MarcGravell, foo.Method ((dinamik) myGenericClass) 'işlevini çalışma zamanı yöntemi için kullanabilirsiniz. Bir tipin metot aşırı yüklenmesi için etkin bir şekilde servis belirleyici paterni. –

cevap

173

Bunu yansıma olmadan yapamazsınız. Ancak, ,'u yansımayla yapabilir.

using System; 
using System.Reflection; 

public class Generic<T> 
{ 
    public Generic() 
    { 
     Console.WriteLine("T={0}", typeof(T)); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     string typeName = "System.String"; 
     Type typeArgument = Type.GetType(typeName); 

     Type genericClass = typeof(Generic<>); 
     // MakeGenericType is badly named 
     Type constructedClass = genericClass.MakeGenericType(typeArgument); 

     object created = Activator.CreateInstance(constructedClass); 
    } 
} 

Not: Burada tam bir örnek

Type genericClass = typeof(IReadOnlyDictionary<,>); 
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2); 
+0

Tamam, bu iyi, ama nasıl oluşturuldu? Daha fazla yansıma mı? –

+3

Peki, jenerik türünüzün genel olmayan bir arayüz oluşturmasını sağlayabilirsiniz, bu arayüze yayın yapabilirsiniz. Alternatif olarak, jenerik ile yapmak istediğiniz tüm işleri yapan kendi genel yönteminizi yazabilir ve yansıma ile * diyebilirsiniz. –

+0

(Bu durumda, MakeGenericType etc'yi çağırmanız gerekmeyecektir, çünkü jenerik türün örneğinin oluşturulması genel yöntem içinde de yapılabilecektir.) –

14

Maalesef yok. Genel argümanlar, Derleme zamanında 1) geçerli bir tür veya 2) başka bir genel parametre olarak çözülebilir olmalıdır. büyük çekiç olmadan çalışma zamanı değerlerine dayalı genel örnekler oluşturmak için yansımanın kullanılması.

1

Bazı ek nasıl çalıştırılacağı: En genel sınıf birden fazla türde kabul ederse, örneğin, tip isimleri atladığınızda, Virgül gerekir makas kodu. Eğer Ancak

var fooContents = new List<FooContent>(fooContent) 
new Encoder().Markdown(fooContents) 

isteyeyim Eğer

public class Encoder() { 
public void Markdown(IEnumerable<FooContent> contents) { do magic } 
public void Markdown(IEnumerable<BarContent> contents) { do magic2 } 
} 

benzer bir sınıf var zamanında derleme zamanında bağlamak başardık Bir FooContent

varsayalım olduğunu varsayalım, bunu çalışma zamanında yapamazsınız. zamanında Bunu yapmak için çizgisinde yapacağını:

var listType = typeof(List<>).MakeGenericType(myType); 
var dynamicList = Activator.CreateInstance(listType); 
((IList)dynamicList).Add(fooContent); 

dinamik yöntem çağrısında Markdown(IEnumerable<FooContent> contents)

new Encoder().Markdown((dynamic) dynamicList) 

Not Ekle dynamic kullanımını çağırmak için. Çalışma zamanında dynamicListList<FooContent> olacaktır (ek olarak IEnumerable<FooContent> da olacaktır), çünkü dinamik kullanım bile güçlü bir şekilde yazılmış bir dile köklenmiş olduğundan çalışma zamanı bağlayıcısı uygun Markdown yöntemini seçecektir. Tam tür eşleşmeler yoksa, bir nesne parametresi yöntemi arar ve hiçbir yöntem eşleşmediği konusunda bir çalışma zamanı bağlayıcısı istisnasıyla eşleşmeyecek şekilde yükseltilir.

Bu yaklaşıma geri çekiliş, derleme zamanında büyük bir tip güvenlik kaybıdır. Yine de, bu satırlardaki kodlar, çalışma zamanında tam olarak beklediğiniz gibi yazıldığından çok dinamik bir şekilde çalışmanıza izin verir.

2

Gereksinimlerim biraz farklıydı, ama umarım birilerine yardım eder. Bir yapılandırmadan tür okumalı ve genel tipini dinamik olarak başlatmalıydım.

namespace GenericTest 
{ 
    public class Item 
    { 
    } 
} 

namespace GenericTest 
{ 
    public class GenericClass<T> 
    { 
    } 
} 

Son olarak, işte böyle diyorsunuz. Define the type with a backtick.

var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest"); 
var a = Activator.CreateInstance(t); 
İlgili konular