Как я могу получить общий тип из строкового представления?
У меня MyClass<T>
.
И тогда у меня есть это string s = "MyClass<AnotherClass>";
. Как получить тип из строки s
?
Один из способов (уродливый) - разобрать "<" и " > " и выполните:
Type acType = Type.GetType("AnotherClass");
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType);
Но есть ли более чистый способ получить окончательный тип без разбора и т.д.?
Ответы
Ответ 1
Формат для дженериков - это имя, символ, количество параметров типа, за которым следует список типов с разделителями-запятыми в скобках:
Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]");
Я не уверен, что есть простой способ конвертировать из синтаксиса С# для генериков в тип строки, которую хочет CLR. Я начал писать быстрое регулярное выражение, чтобы разобрать его, как вы упомянули в вопросе, но понял, что, если вы не откажетесь от возможности иметь вложенные дженерики в качестве параметров типа, синтаксический анализ будет очень сложным.
Ответ 2
Отъезд Activator.CreateInstance
- вы можете вызвать его с типом
Activator.CreateInstance(typeof(MyType))
или с именем сборки и типа как string
Activator.CreateInstance("myAssembly", "myType")
Это даст вам экземпляр типа, который вам нужен.
Если вам нужен Type
, а не экземпляр, используйте метод Type.GetType()
и полное имя интересующего вас типа, например:
string s = "System.Text.StringBuilder";
Type myClassType = Type.GetType(s);
Это даст вам Type
.
Ответ 3
Мне нужно что-то вроде этого, и я закончил тем, что написал код, чтобы разобрать простые имена типов, которые мне нужны. Конечно, есть возможности для улучшения, поскольку он не будет идентифицировать типичные имена типов, такие как List<string>
, но он отлично подходит для string
, int[]
, decimal?
и тому подобного. Совместное использование в случае, если это поможет кому-либо.
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);
}
}
Использование его так же просто, как написать это:
Type t;
t = TypeExtensions.GetTypeFromSimpleName("string");
t = TypeExtensions.GetTypeFromSimpleName("int[]");
t = TypeExtensions.GetTypeFromSimpleName("decimal?");
Ответ 4
Чтобы просто получить объект типа из строки, используйте:
Type mytype = Type.GetType(typeName);
Затем вы можете передать это на Activator.CreateInstance()
:
Activator.CreateInstance(mytype);
Ответ 5
У меня не так много времени, чтобы разобраться в этом, хотя я думаю, что видел некоторые подобные ответы. В частности, я думаю, что они делают именно то, что вы хотите сделать здесь:
Ошибка общего репозитория Framework Entity Framework
(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>();
Надеюсь, это поможет, дайте мне знать более конкретно, если это не так.