Pertanyaan Bagaimana saya bisa mendapatkan Tipe generik dari representasi string?


saya sudah MyClass<T>.

Dan kemudian saya punya ini string s = "MyClass<AnotherClass>";. Bagaimana saya bisa mendapatkan Type dari string s?

Salah satu cara (jelek) adalah mengurai "<" dan ">" dan melakukan:

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

Tetapi apakah ada cara yang lebih bersih untuk mendapatkan jenis terakhir tanpa parsing, dll?


76
2018-04-06 15:03


asal


Jawaban:


Itu format untuk generik adalah nama, karakter `, jumlah parameter jenis, diikuti oleh daftar jenis yang dibatasi koma dalam kurung siku:

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

Saya tidak yakin ada cara mudah untuk mengkonversi dari sintaks C # untuk generik ke jenis string yang diinginkan CLR. Saya mulai menulis regex cepat untuk menguraikannya seperti yang Anda sebutkan dalam pertanyaan, tetapi menyadari bahwa kecuali Anda menyerah kemampuan untuk memiliki generik bertingkat sebagai parameter jenis parsing akan menjadi sangat rumit.


91
2018-04-06 15:36



Periksa Activator.CreateInstance - Anda bisa menyebutnya dengan tipe

Activator.CreateInstance(typeof(MyType))

atau dengan perakitan dan ketik nama sebagai string

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

Ini akan memberi Anda contoh jenis yang Anda butuhkan.

Jika Anda membutuhkan Type daripada instance, gunakan Type.GetType() metode dan nama yang memenuhi syarat dari jenis yang Anda minati, misalnya:

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

Itu akan memberi Anda Type dalam pertanyaan.


38
2018-04-06 15:06



Saya membutuhkan sesuatu seperti ini dan saya akhirnya menulis beberapa kode untuk mengurai nama-nama sederhana yang saya butuhkan. Tentu saja ada ruang untuk perbaikan, karena tidak akan mengidentifikasi nama tipe generik seperti List<string>, tapi itu baik-baik saja string, int[], decimal? dan seperti. Berbagi jika ini membantu siapa saja.

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

Menggunakannya sesederhana menulis ini:

Type t;

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

26
2018-02-09 14:00



Untuk mendapatkan jenis objek dari string, gunakan:

Type mytype = Type.GetType(typeName);

Anda kemudian dapat meneruskan ini Activator.CreateInstance():

Activator.CreateInstance(mytype);

3
2018-04-06 15:12



Saya tidak punya banyak waktu untuk menguraikan ini, meskipun saya pikir saya telah melihat beberapa jawaban yang serupa. Secara khusus, saya pikir mereka melakukan apa yang ingin Anda lakukan di sini:

Entity Framework Generic Repository Error

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

Semoga ini membantu, beri tahu saya lebih spesifik jika ini tidak membantu.


0
2018-04-06 15:10