2009-04-06 22 views
76

MyClass<T> ürünüm var.Genel Türü bir dize temsilinden nasıl alabilirim?

Ve daha sonra bu string s = "MyClass<AnotherClass>"; var. Type s dizesinden nasıl alabilirim?

Tek yön (çirkin) "<" ve ">" dışarı ayrıştırmak ve yapmaktır:

Type acType = Type.GetType("AnotherClass"); 
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType); 

Ama son tipini almak için temizleyici bir yolu vb herhangi ayrıştırma olmadan var mı?

cevap

90

format for generics isim, bir `karakter, sayı parantez içinde türlerin virgülle ayrılmış bir listesi tarafından takip edilen tip parametrelerinin izlenmesi:

Jenerikler için C# sözdizimini CLR'nin istediği dizeye dönüştürmenin kolay bir yolu olduğundan emin değilim. Sorguda bahsettiğiniz gibi ayrıştırmak için hızlı bir regex yazmaya başladım, ama tür parametreler olarak yuvalanmış jeneriklere sahip olma yeteneğinden vazgeçmediğiniz sürece ayrışmanın çok karmaşık olacağını fark ettiniz.

+0

+1 - harika cevap, teşekkürler! Jeneriklerin nasıl ele alınacağını öğrenmek için uğraşıyordum! –

+0

Teşekkürler. Bu çalışır ve bu şekilde dize biçimlendirmek için kodu değiştirmek zorunda. Bununla birlikte, basitçe kullanmanın bir yolu olup olmadığını merak ediyordum: "MyClass " tam olarak, Type örneğini almak için dizede gösterildiği gibi. Çok daha temiz görünüyor. – DeeStackOverflow

+0

Dizeyi bu şekilde biçimlendirmek için kodu değiştirmeniz gerekmez, yalnızca Tür'deki ToString() öğesini arayın. –

38

Kontrol dışarı Activator.CreateInstance - Eğer size ihtiyacınız türünün bir örneği verecek string

Activator.CreateInstance("myAssembly", "myType") 

Bu gibi bir tip

Activator.CreateInstance(typeof(MyType)) 

veya bir montaj ve tip adı ile birlikte diyebilirsin.

string s = "System.Text.StringBuilder"; 
Type myClassType = Type.GetType(s); 

Yani Type söz konusu vereceğim:

Eğer bir örneği değil Type yerine gerekiyorsa, Type.GetType() yöntem ve ilgilendiğiniz tip tam adını, örneğin kullanmak .

+2

ne OP gibi görünüyor için bakıyor. –

0

Bunun ile ayrıştırmak için fazla zamanım yok, ama sanırım bazı benzer cevapları gördüm. Özellikle, onlar burada ne yapmak istediğini tam olarak yaptığını düşünüyorum:

Entity Framework Generic Repository Error

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>(); 

Umarım bu yardımcı olur, bu değilse bana daha spesifik bildirin.

3

sadece dizesinden tipi nesnesini almak için kullanın:

Type mytype = Type.GetType(typeName); 

Sonra Activator.CreateInstance() bu geçirebilirsiniz:

Activator.CreateInstance(mytype); 
26

Böyle bir şeye ihtiyacım vardı ve ihtiyacım olan basit tür adlarını ayrıştırmak için kod yazmayı bitirdim. Tabii ki, List<string> gibi jenerik tür isimleri tanımlamayacak şekilde iyileştirme için bir yer var, ancak string, int[], decimal? ve benzeri için gayet iyi. Paylaşmak durumunda bu herkesin yardımcı olur.Bunu kullanarak

public static class TypeExtensions 
{ 
    public static Type GetTypeFromSimpleName(string typeName) 
    { 
    if (typeName == null) 
     throw new ArgumentNullException("typeName"); 

    bool isArray = false, isNullable = false; 

    if (typeName.IndexOf("[]") != -1) 
    { 
     isArray = true; 
     typeName = typeName.Remove(typeName.IndexOf("[]"), 2); 
    } 

    if (typeName.IndexOf("?") != -1) 
    { 
     isNullable = true; 
     typeName = typeName.Remove(typeName.IndexOf("?"), 1); 
    } 

    typeName = typeName.ToLower(); 

    string parsedTypeName = null; 
    switch (typeName) 
    { 
     case "bool": 
     case "boolean": 
     parsedTypeName = "System.Boolean"; 
     break; 
     case "byte": 
     parsedTypeName = "System.Byte"; 
     break; 
     case "char": 
     parsedTypeName = "System.Char"; 
     break; 
     case "datetime": 
     parsedTypeName = "System.DateTime"; 
     break; 
     case "datetimeoffset": 
     parsedTypeName = "System.DateTimeOffset"; 
     break; 
     case "decimal": 
     parsedTypeName = "System.Decimal"; 
     break; 
     case "double": 
     parsedTypeName = "System.Double"; 
     break; 
     case "float": 
     parsedTypeName = "System.Single"; 
     break; 
     case "int16": 
     case "short": 
     parsedTypeName = "System.Int16"; 
     break; 
     case "int32": 
     case "int": 
     parsedTypeName = "System.Int32"; 
     break; 
     case "int64": 
     case "long": 
     parsedTypeName = "System.Int64"; 
     break; 
     case "object": 
     parsedTypeName = "System.Object"; 
     break; 
     case "sbyte": 
     parsedTypeName = "System.SByte"; 
     break; 
     case "string": 
     parsedTypeName = "System.String"; 
     break; 
     case "timespan": 
     parsedTypeName = "System.TimeSpan"; 
     break; 
     case "uint16": 
     case "ushort": 
     parsedTypeName = "System.UInt16"; 
     break; 
     case "uint32": 
     case "uint": 
     parsedTypeName = "System.UInt32"; 
     break; 
     case "uint64": 
     case "ulong": 
     parsedTypeName = "System.UInt64"; 
     break; 
    } 

    if (parsedTypeName != null) 
    { 
     if (isArray) 
     parsedTypeName = parsedTypeName + "[]"; 

     if (isNullable) 
     parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]"); 
    } 
    else 
     parsedTypeName = typeName; 

    // Expected to throw an exception in case the type has not been recognized. 
    return Type.GetType(parsedTypeName); 
    } 
} 

bu yazmak kadar basit: Bu sadece kod parçacığı dayalı tip değil, bir System.Type örneği, bir örneğini alır

Type t; 

t = TypeExtensions.GetTypeFromSimpleName("string"); 
t = TypeExtensions.GetTypeFromSimpleName("int[]"); 
t = TypeExtensions.GetTypeFromSimpleName("decimal?"); 
+5

Bu, inanılmaz derecede kullanışlı bir kod parçasıdır. –

+1

Kısa, Mükemmel, Son Derece Kullanışlı! Teşekkürler – xrnd

İlgili konular