method - reflection c# español
¿Cómo puedo obtener un tipo genérico a partir de una representación de cadena? (5)
Tengo MyClass<T>
.
Y luego tengo esta string s = "MyClass<AnotherClass>";
. ¿Cómo puedo obtener Tipo de la cadena s
?
Una forma (fea) es analizar el "<" y ">" y hacer:
Type acType = Type.GetType("AnotherClass");
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType);
Pero, ¿hay una manera más clara de obtener el tipo final sin ningún análisis sintáctico, etc.?
Echa un vistazo a Activator.CreateInstance
: puedes llamarlo con un tipo
Activator.CreateInstance(typeof(MyType))
o con un ensamblaje y nombre de tipo como string
Activator.CreateInstance("myAssembly", "myType")
Esto le dará una instancia del tipo que necesita.
Si necesita el Type
lugar de la instancia, use el método Type.GetType()
y el nombre completo del tipo que le interesa, por ejemplo:
string s = "System.Text.StringBuilder";
Type myClassType = Type.GetType(s);
Eso te dará el Type
en cuestión.
El formato para genéricos es el nombre, un carácter `, el número de parámetros de tipo, seguido de una lista delimitada por comas de los tipos entre paréntesis:
Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]");
No estoy seguro de que haya una manera fácil de convertir la sintaxis de C # para los genéricos al tipo de cadena que quiere el CLR. Empecé a escribir una expresión regular rápida para analizarla como mencionaste en la pregunta, pero me di cuenta de que a menos que abandones la capacidad de tener genéricos anidados como parámetros de tipo, el análisis se volverá muy complicado.
He necesitado algo así y terminé escribiendo un código para analizar los nombres de tipos simples que necesitaba. Por supuesto, hay margen de mejora, ya que no identificará los nombres de tipos genéricos como List<string>
, pero sí se aplica a string
, int[]
, decimal?
y tal. Compartir en caso de que esto ayude a alguien.
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);
}
}
Usarlo es tan simple como escribir esto:
Type t;
t = TypeExtensions.GetTypeFromSimpleName("string");
t = TypeExtensions.GetTypeFromSimpleName("int[]");
t = TypeExtensions.GetTypeFromSimpleName("decimal?");
No tengo mucho tiempo para analizar todo esto, aunque creo que he visto algunas respuestas similares. En particular, creo que están haciendo exactamente lo que quieres hacer aquí:
Error de repositorio genérico de Entity Framework
(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>();
Espero que esto ayude, hágamelo saber más específicamente si esto no es así.
Para obtener el objeto tipo de la cadena, use:
Type mytype = Type.GetType(typeName);
A continuación, puede pasar esto a Activator.CreateInstance()
:
Activator.CreateInstance(mytype);