Как найти System.Type из сложной строки полного пути? - PullRequest
0 голосов
/ 30 августа 2018

Например, мой Тип является сложным типом, это универсальный тип.

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, он возвращает ноль. универсальный тип и тип параметра находятся в разных сборках.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Если у вас есть общие типы, вы должны делать это один шаг за другим. Сначала получите общий тип:

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

0 голосов
/ 30 августа 2018
    /// <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;
    }

Я нашел решение здесь: Загрузка универсального типа по имени, когда аргументы универсального типа приходят из нескольких сборок

...