例如,我的类型是一个复杂类型,它是一个泛型类型。
public class TestType<T> : xxx
{
}
这是Assmebly A中的泛型类。 我的程序集B参考A,还有另一个类型TestObject。 所以实际的类型是:
TestType<TestObject>
... 如果我保存此类型的全名,则它是一个非常复杂的字符串,如下所示:
BluePrint.Core.CustomObjectConverter`1[[BluePrint.SGame.VInt2, BluePrint.SGame.Plugins, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], BluePrint.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
那么,如果我想找到此字符串的System.Type
,该怎么做?
我使用System.Type.GetType
,它返回null。
通用类型和参数类型在不同的程序集中。
答案 0 :(得分:0)
/// <summary>
/// Gets the type associated with the specified name.
/// </summary>
/// <param name="typeName">Full name of the type.</param>
/// <param name="type">The type.</param>
/// <param name="customAssemblies">Additional loaded assemblies (optional).</param>
/// <returns>Returns <c>true</c> if the type was found; otherwise <c>false</c>.</returns>
public static bool TryGetTypeByName(string typeName, out Type type, params Assembly[] customAssemblies)
{
if (typeName.Contains("Version=")
&& !typeName.Contains("`"))
{
// remove full qualified assembly type name
typeName = typeName.Substring(0, typeName.IndexOf(','));
}
type = Type.GetType(typeName);
if (type == null)
{
type = GetTypeFromAssemblies(typeName, customAssemblies);
}
// try get generic types
if (type == null
&& typeName.Contains("`"))
{
var match = Regex.Match(typeName, "(?<MainType>.+`(?<ParamCount>[0-9]+))\\[(?<Types>.*)\\]");
if (match.Success)
{
int genericParameterCount = int.Parse(match.Groups["ParamCount"].Value);
string genericDef = match.Groups["Types"].Value;
List<string> typeArgs = new List<string>(genericParameterCount);
foreach (Match typeArgMatch in Regex.Matches(genericDef, "\\[(?<Type>.*?)\\],?"))
{
if (typeArgMatch.Success)
{
typeArgs.Add(typeArgMatch.Groups["Type"].Value.Trim());
}
}
Type[] genericArgumentTypes = new Type[typeArgs.Count];
for (int genTypeIndex = 0; genTypeIndex < typeArgs.Count; genTypeIndex++)
{
Type genericType;
if (TryGetTypeByName(typeArgs[genTypeIndex], out genericType, customAssemblies))
{
genericArgumentTypes[genTypeIndex] = genericType;
}
else
{
// cant find generic type
return false;
}
}
string genericTypeString = match.Groups["MainType"].Value;
Type genericMainType;
if (TryGetTypeByName(genericTypeString, out genericMainType))
{
// make generic type
type = genericMainType.MakeGenericType(genericArgumentTypes);
}
}
}
return type != null;
}
private static Type GetTypeFromAssemblies(string typeName, params Assembly[] customAssemblies)
{
Type type = null;
if (customAssemblies != null
&& customAssemblies.Length > 0)
{
foreach (var assembly in customAssemblies)
{
type = assembly.GetType(typeName);
if (type != null)
return type;
}
}
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in loadedAssemblies)
{
type = assembly.GetType(typeName);
if (type != null)
return type;
}
return type;
}
我在这里找到解决方案: Loading a generic type by name when the generics arguments come from multiple assemblies
答案 1 :(得分:0)
如果具有通用类型,则需要一个接一个地执行此步骤。 首先,获取通用类型:
typeof(BluePrint.Core.CustomObjectConverter<>).FullName
这应该给你
"BluePrint.Core.CustomObjectConverter`1"
您可以将其传递给GetType
var genericType = Type.GetType("BluePrint.Core.CustomObjectConverter`1")
,然后获取其特定类型:
genericType.MakeGenericType("BluePrint.SGame.VInt2")
知道这一点,并且只有一个字符串时,您可以解析该字符串并在下一步骤之后建立您的类型。
如果尚未将程序集加载到您的空间中,则可以使用GetType的重载来找到它们:https://msdn.microsoft.com/en-us/library/ee332978(v=vs.110).aspx