• Type序列化器


    用于将Type和Type名称相互转化

    public class TypeNameSerializer 
        {
            private readonly ConcurrentDictionary<Type, string> serializedTypes = new ConcurrentDictionary<Type, string>();
            private readonly ConcurrentDictionary<string, Type> deSerializedTypes = new ConcurrentDictionary<string, Type>();
    
            /// <inheritdoc />
            public string Serialize(Type type)
            {
                return serializedTypes.GetOrAdd(type, t =>
                {
                    var typeName = RemoveAssemblyDetails(t.AssemblyQualifiedName);
                    return typeName;
                });
            }
    
            /// <inheritdoc />
            public Type DeSerialize(string typeName)
            {
                return deSerializedTypes.GetOrAdd(typeName, t =>
                {
                    var typeNameKey = SplitFullyQualifiedTypeName(t);
                    return GetTypeFromTypeNameKey(typeNameKey);
                });
            }
    
            private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
            {
                var builder = new StringBuilder(fullyQualifiedTypeName.Length);
    
                // loop through the type name and filter out qualified assembly details from nested type names
                var writingAssemblyName = false;
                var skippingAssemblyDetails = false;
                foreach (var character in fullyQualifiedTypeName)
                {
                    switch (character)
                    {
                        case '[':
                            writingAssemblyName = false;
                            skippingAssemblyDetails = false;
                            builder.Append(character);
                            break;
                        case ']':
                            writingAssemblyName = false;
                            skippingAssemblyDetails = false;
                            builder.Append(character);
                            break;
                        case ',':
                            if (!writingAssemblyName)
                            {
                                writingAssemblyName = true;
                                builder.Append(character);
                            }
                            else
                            {
                                skippingAssemblyDetails = true;
                            }
                            break;
                        default:
                            if (!skippingAssemblyDetails)
                            {
                                builder.Append(character);
                            }
                            break;
                    }
                }
    
                return builder.ToString();
            }
    
            private static TypeNameKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName)
            {
                var assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
    
                string typeName;
                string assemblyName;
    
                if (assemblyDelimiterIndex != null)
                {
                    typeName = Trim(fullyQualifiedTypeName,0, assemblyDelimiterIndex.GetValueOrDefault());
                    assemblyName = Trim(fullyQualifiedTypeName,assemblyDelimiterIndex.GetValueOrDefault() + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.GetValueOrDefault() - 1);
                }
                else
                {
                    typeName = fullyQualifiedTypeName;
                    assemblyName = null;
                }
    
                return new TypeNameKey(assemblyName, typeName);
            }
    
            private static Type GetTypeFromTypeNameKey(TypeNameKey typeNameKey)
            {
                var assemblyName = typeNameKey.AssemblyName;
                var typeName = typeNameKey.TypeName;
    
                if (assemblyName != null)
                {
    
                    var assembly = Assembly.Load(new AssemblyName(assemblyName));
                    if (assembly == null)
                    {
                        var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
                        foreach (var a in loadedAssemblies)
                        {
                            if (a.FullName == assemblyName || a.GetName().Name == assemblyName)
                            {
                                assembly = a;
                                break;
                            }
                        }
                    }
    
                    if (assembly == null)
                    {
                        throw new Exception($"Could not load assembly '{assemblyName}'");
                    }
    
                    var type = assembly.GetType(typeName);
                    if (type == null)
                    {
                        // if generic type, try manually parsing the type arguments for the case of dynamically loaded assemblies
                        // example generic typeName format: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
                        if (typeName.IndexOf('`') >= 0)
                        {
                            try
                            {
                                type = GetGenericTypeFromTypeName(typeName, assembly);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception($"Could not find type '{typeName}' in assembly '{assembly.FullName}'", ex);
                            }
                        }
    
                        if (type == null)
                        {
                            throw new Exception($"Could not find type '{typeName}' in assembly '{assembly.FullName}'");
                        }
                    }
    
                    return type;
                }
    
                return Type.GetType(typeName);
            }
    
            private static Type GetGenericTypeFromTypeName(string typeName, Assembly assembly)
            {
                Type type = null;
                var openBracketIndex = typeName.IndexOf('[');
                if (openBracketIndex >= 0)
                {
                    var genericTypeDefName = typeName.Substring(0, openBracketIndex);
                    var genericTypeDef = assembly.GetType(genericTypeDefName);
                    if (genericTypeDef != null)
                    {
                        var genericTypeArguments = new List<Type>();
                        var scope = 0;
                        var typeArgStartIndex = 0;
                        var endIndex = typeName.Length - 1;
                        for (var i = openBracketIndex + 1; i < endIndex; ++i)
                        {
                            var current = typeName[i];
                            switch (current)
                            {
                                case '[':
                                    if (scope == 0)
                                    {
                                        typeArgStartIndex = i + 1;
                                    }
                                    ++scope;
                                    break;
                                case ']':
                                    --scope;
                                    if (scope == 0)
                                    {
                                        var typeArgAssemblyQualifiedName = typeName.Substring(typeArgStartIndex, i - typeArgStartIndex);
                                        var typeNameKey = SplitFullyQualifiedTypeName(typeArgAssemblyQualifiedName);
                                        genericTypeArguments.Add(GetTypeFromTypeNameKey(typeNameKey));
                                    }
                                    break;
                            }
                        }
    
                        type = genericTypeDef.MakeGenericType(genericTypeArguments.ToArray());
                    }
                }
    
                return type;
            }
    
            private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
            {
                // we need to get the first comma following all surrounded in brackets because of generic types
                // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
                var scope = 0;
                for (var i = 0; i < fullyQualifiedTypeName.Length; i++)
                {
                    var current = fullyQualifiedTypeName[i];
                    switch (current)
                    {
                        case '[':
                            scope++;
                            break;
                        case ']':
                            scope--;
                            break;
                        case ',':
                            if (scope == 0)
                            {
                                return i;
                            }
                            break;
                    }
                }
    
                return null;
            }
    
            public static string Trim(string s, int start, int length)
            {
                // References: https://referencesource.microsoft.com/#mscorlib/system/string.cs,2691
                // https://referencesource.microsoft.com/#mscorlib/system/string.cs,1226
                if (s == null)
                {
                    throw new ArgumentNullException(nameof(s));
                }
                if (start < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(start));
                }
                if (length < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(length));
                }
    
                var end = start + length - 1;
                if (end >= s.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(length));
                }
                for (; start < end; start++)
                {
                    if (!char.IsWhiteSpace(s[start]))
                    {
                        break;
                    }
                }
                for (; end >= start; end--)
                {
                    if (!char.IsWhiteSpace(s[end]))
                    {
                        break;
                    }
                }
                return s.Substring(start, end - start + 1);
            }
    
            private struct TypeNameKey
            {
                public string AssemblyName { get; }
                public string TypeName { get; }
    
                public TypeNameKey(string assemblyName, string typeName)
                {
                    AssemblyName = assemblyName;
                    TypeName = typeName;
                }
            }
        }
    

    客户端:

    public static void Main(string[] args)
            {
                TypeNameSerializer serializer = new TypeNameSerializer();
                //将Type序列化为Name
               string typeName = serializer.Serialize(typeof(Program));
                //将Name反序列化为Type
                Type type = serializer.DeSerialize(typeName);
    
                //泛型
                typeName = serializer.Serialize(typeof(People<>));
                type = serializer.DeSerialize(typeName);
                Console.ReadKey();
                return;
          }
    
  • 相关阅读:
    一些文件的扩展名
    关于git,从svn转到git
    trousers--------dpkg: 处理软件包 trousers (--configure)时报错
    Ubuntu下运行DrClient以上网
    Ubuntu下的终端命令--复制文件从一个文件夹到另一个文件夹下
    VSCode放大字体的快捷键
    opessl版本过低造成的函数使用错误
    python的基本语法
    ubuntu和windows的解码方式
    ubuntu下强制删除文件夹
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/13680740.html
Copyright © 2020-2023  润新知