Soru Genel Türü bir dize temsilinden nasıl alabilirim?


Sahibim MyClass<T>.

Ve sonra bende var string s = "MyClass<AnotherClass>";. Dize türünü nasıl alabilirim s?

Bir yol (çirkin) "<" ve ">" yi ayrıştırmak ve yapmak:

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

Ama herhangi bir ayrıştırma, vb olmadan son tür almak için daha temiz bir yolu var mı?


76
2018-04-06 15:03


Menşei




Cevaplar:


jenerikler için format ad, bir `karakter, tür parametrelerinin sayısı ve ardından parantez içindeki türlerin virgülle ayrılmış listesidir:

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]");

C # sözdizimi için jenerik için CLR'nin istediği string türüne 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.


91
2018-04-06 15:36



+1 - harika cevap, teşekkürler! Jeneriklerin nasıl ele alınacağını öğrenmek için uğraşıyordum! - marc_s
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 <AnotherClass>" tam olarak, Type örneğini almak için dizede gösterildiği gibi. Çok daha temiz görünüyor. - DeeStackOverflow
Dize bu şekilde biçimlendirmek için kodu değiştirmek zorunda değilsiniz, sadece Tür üzerinde ToString () öğesini çağırın. - Rush Frisby


Çıkış yapmak Activator.CreateInstance - bir türle arayabilirsin

Activator.CreateInstance(typeof(MyType))

veya bir montaj ve tip adıyla string

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

Bu size ihtiyacınız olan türün bir örneğini verecektir.

Gerekiyorsa Type örneğinden ziyade, Type.GetType() yöntem ve ilgilendiğiniz türün tam adı. Ör .:

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

Bu sana verecek Type söz konusu.


38
2018-04-06 15:06



Bu sadece bir örnek alır, bir kod, kod parçacığını temel alan bir System.Type örneği değil, OP'nin aradığı gibi görünür. - Daniel Schaffer


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

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

Bunu kullanarak yazmak şu kadar basit:

Type t;

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

26
2018-02-09 14:00



Bu inanılmaz derecede kullanışlı bir kod. - The Communist Duck
Kısa, Mükemmel, Son Derece Faydalı! Teşekkürler - xrnd


Yalnızca dize nesnesini almak için şunu kullanın:

Type mytype = Type.GetType(typeName);

Bunu daha sonra iletebilirsiniz Activator.CreateInstance():

Activator.CreateInstance(mytype);

3
2018-04-06 15:12





Bunu çözümlemek için fazla zamanım yok, sanırım bazı benzer cevapları gördüm. Özellikle, burada yapmak istediğiniz şeyi tam olarak yaptığını düşünüyorum:

Varlık Framework Genel Deposu Hatası

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

Umarım bu yardımcı olur, eğer bilmiyorum, özellikle bilmesin.


0
2018-04-06 15:10