C#泛型类型声明

C#泛型类型声明,c#,generics,reflection,.net-4.0,types,C#,Generics,Reflection,.net 4.0,Types,是否有可能获得通过反射获得的类型的“c#name”,如: System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 我想得到: List<String> 列表 是否可以不拆分字符串?例如,使用反射 谢谢 …不分线 好的,否您需要解析如下字符串: t`x[[a(,b,c,d)]] 式

是否有可能获得通过反射获得的类型的“c#name”,如:

System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
我想得到:

List<String>
列表
是否可以不拆分字符串?例如,使用反射

谢谢

…不分线


好的,

您需要解析如下字符串:

t`x[[a(,b,c,d)]]

式中,t为实际类型;x——通用参数的数量;a、 b、c、d等-泛型aguments

不是直接的,但是您可以检查类型本身来找出它

public static string TypeName(Type t) {
    if (!t.IsGenericType) return t.Name;

    StringBuilder ret = new StringBuilder();
    ret.Append(t.Name).Append("<");

    bool first = true;
    foreach(var arg in t.GetGenericArguments()) {
        if (!first) ret.Append(", ");
        first = false;

        ret.Append(TypeName(arg));
    }

    ret.Append(">");
    return ret.ToString();
}
公共静态字符串类型名(类型t){
如果(!t.IsGenericType)返回t.Name;
StringBuilder ret=新的StringBuilder();
ret.Append(t.Name).Append(“”);
返回ret.ToString();
}

是的,您可以使用and进行操作,而无需使用拆分、解析或操纵字符串:

使用CodeDom;
使用Microsoft.CSharp;
// ...
键入yourType=typeof(List);//例如
使用(var provider=new CSharpCodeProvider())
{
var typeRef=新的代码类型引用(yourType);
Console.WriteLine(provider.GetTypeOutput(typeRef));
}

(您可能需要执行一些额外的字符串操作来删除名称空间前缀。例如,如果您希望输出为
List
,而不是
System.Collections.Generic.List

您可以检查该类型是否嵌套,以及它是泛型构造的还是基元类型。我特别意识到嵌套泛型类型在类型名称字符串的末尾列出了它的泛型参数。文件中提到了这一点

我已经部分解决了任务,并且我的解决方案通过了以下测试

        [TestMethod]
        public void Tests()
        {

            Assert.AreEqual("int",typeof(int).ToCSharpMethodReturnTypeName());
            Assert.AreEqual("int[]",typeof(int[]).ToCSharpMethodReturnTypeName());
            Assert.AreEqual("int?", typeof(int?).ToCSharpMethodReturnTypeName());

            Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Inner2<string,IDictionary<string,object>>.SubInner<int,List<byte[]>,object>", typeof(Inner2<string,IDictionary<string,object>>.SubInner<int,List<byte[]>,object>).ToCSharpMethodReturnTypeName());

            Assert.ThrowsException<NotImplementedException>(()=> typeof(Inner2<string, IDictionary<string, object>>.SubInner<int, List<byte[]>, object>).DeclaringType.ToCSharpMethodReturnTypeName());

            var t = typeof(TestGenericReturnType<DateTime>);
            var m = t.GetMethod("GetService");
            var tt = m.ReturnType;

            Assert.AreEqual("DateTime",tt.ToCSharpMethodReturnTypeName());

            Assert.AreEqual("IDictionary<string,object>",typeof(IDictionary<string,object>).ToCSharpMethodReturnTypeName());
            Assert.AreEqual("IList<int[]>",typeof(IList<int[]>).ToCSharpMethodReturnTypeName());
            Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Astruc?",typeof(Astruc?).ToCSharpMethodReturnTypeName());
            Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Inner", typeof(Inner).ToCSharpMethodReturnTypeName());
        }
[TestMethod]
公开无效测试()
{
AreEqual(“int”,typeof(int).ToCSharpMethodReturnTypeName());
AreEqual(“int[]”,typeof(int[]).ToCSharpMethodReturnTypeName();
AreEqual(“int?”,typeof(int?).ToCSharpMethodReturnTypeName();
AreEqual(“unittypefriendlynamesextensiontest.Inner2.SubInner”、typeof(Inner2.SubInner.tosharpmethodreturntypename());
Assert.ThrowsException(()=>typeof(Inner2.SubInner).DeclaringType.ToCSharpMethodReturnTypeName());
var t=typeof(TestGenericReturnType);
var m=t.GetMethod(“GetService”);
var tt=m.ReturnType;
AreEqual(“DateTime”,tt.ToCSharpMethodReturnTypeName());
AreEqual(“IDictionary”,typeof(IDictionary.ToCSharpMethodReturnTypeName());
AreEqual(“IList”,typeof(IList).ToCSharpMethodReturnTypeName());
AreEqual(“UnitTypeFriendlyNameSextensionTest.Astruc?”,typeof(Astruc?).ToSharpMethodReturnTypeName());
AreEqual(“UnitTypeFriendlyNameSextensionTest.Inner”,typeof(Inner).toSharpMethodReturnTypeName());
}
extensions类处理嵌套和泛型构造的类型以及基元类型

public static class TypeFriendlyNamesExtensions
{
    private static readonly Dictionary<Type, string> TypeToFriendlyName = new Dictionary<Type, string>
    {
        {typeof(string), "string"},
        {typeof(object), "object"},
        {typeof(bool), "bool"},
        {typeof(byte), "byte"},
        {typeof(char), "char"},
        {typeof(decimal), "decimal"},
        {typeof(double), "double"},
        {typeof(short), "short"},
        {typeof(int), "int"},
        {typeof(long), "long"},
        {typeof(sbyte), "sbyte"},
        {typeof(float), "float"},
        {typeof(ushort), "ushort"},
        {typeof(uint), "uint"},
        {typeof(ulong), "ulong"},
        {typeof(void), "void"}
    };

    public static string ToCSharpMethodReturnTypeName(this Type type)
    {
        var sb = new StringWriter();
        ToCSharpNameEntry2(sb, type);
        return sb.ToString();
    }

    private static void ToCSharpNameEntry2(TextWriter sb, Type type0)
    {
        var list = GetContainingTypeList(type0);
        var usedGenericArgumentCounter = 0;

        HandleNestedLevel(sb, list, 0, ref usedGenericArgumentCounter);
        foreach (var ix in Enumerable.Range(1, list.Count - 1))
        {
            sb.Write(".");
            HandleNestedLevel(sb, list, ix, ref usedGenericArgumentCounter);
        }
    }

    private static void HandleNestedLevel(TextWriter sb, IReadOnlyList<Type> list, int ix,
        ref int usedGenericArgumentCounter)
    {
        var type = list[ix];
        if (TypeToFriendlyName.TryGetValue(type, out string fname))
        {
            sb.Write(fname);
            return;
        }
        if (type.IsGenericParameter)
        {
            sb.Write(type.Name);
            return;
        }
        if (type.IsArray)
        {
            ToCSharpNameEntry2(sb, type.GetElementType());
            sb.Write("[]");
            return;
        }

        if (type.IsGenericType)
        {
            var innermostType = list[list.Count - 1];
            var args = list[list.Count - 1].GenericTypeArguments;
            if (!type.IsConstructedGenericType)
            {
                if (innermostType.IsConstructedGenericType)
                {
                    var sname = GetSname(type);
                    sb.Write(sname);
                    sb.Write("<");
                    ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
                    var loopCounter = ((TypeInfo) type).GenericTypeParameters.Length;
                    while (0 < --loopCounter)
                    {
                        sb.Write(",");
                        ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
                    }
                    sb.Write(">");
                    return;
                }
                throw new NotImplementedException();
            }
            if (typeof(Nullable<>) == type.GetGenericTypeDefinition())
            {
                ToCSharpNameEntry2(sb, args[0]);
                sb.Write("?");
                return;
            }
            var cname = GetSname(type);
            sb.Write(cname);
            sb.Write("<");
            ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
            while (usedGenericArgumentCounter < args.Length)
            {
                sb.Write(",");
                ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
            }
            sb.Write(">");
            return;
        }
        if (type.IsPointer)
        {
            ToCSharpNameEntry2(sb, type);
            sb.Write("*");
            return;
        }
        sb.Write(type.Name);
    }

    private static string GetSname(Type type)
    {
        var name = type.Name;
        return name.Substring(0, name.IndexOf('`'));
    }

    private static List<Type> GetContainingTypeList(Type type)
    {
        var list = new List<Type> {type};
        var t = type;
        while (t.IsNested)
        {
            t = t.DeclaringType;
            list.Insert(0, t);
        }
        return list;
    }

    private static void ToCSharpNameEntry(StringBuilder sb, Type type)
    {
        var genericTypeArguments = type.GenericTypeArguments;
        var usedGenericTypeCounter = 0;
        ToCSharpNameRecursive(sb, type, genericTypeArguments, ref usedGenericTypeCounter);
    }

    private static void ToCSharpNameRecursive(StringBuilder sb, Type type, IReadOnlyList<Type> genericTypeArguments,
        ref int genericTypesCounter)
    {
        if (TypeToFriendlyName.TryGetValue(type, out string res))
        {
            sb.Append(res);
            return;
        }

        HandleNonPriminiveTypes(sb, type, genericTypeArguments, ref genericTypesCounter);
    }

    private static void HandleNonPriminiveTypes(StringBuilder sb, Type type, IReadOnlyList<Type> typeGenericTypeArguments,
        ref int genericTypesCounter)
    {
        var list = new List<Type>();
        var t = type;
        list.Add(t);
        while (t.IsNested)
        {
            t = t.DeclaringType;
            list.Add(t);
        }
        list.Reverse();
        foreach (var type1 in list)
        {
            HandleNestedLevel(sb, type1, typeGenericTypeArguments, ref genericTypesCounter);
            sb.Append(".");
        }
        sb.Length -= 1;
    }

    private static void HandleNestedLevel(StringBuilder sb, Type type, IReadOnlyList<Type> typeGenericTypeArguments,
        ref int genericTypesCounter)
    {
        var name = type.Name;
        if (type.IsGenericType)
        {
            var info = type.GetTypeInfo();
            var def = info.GetGenericTypeDefinition();
            var psLength = info.IsConstructedGenericType
                ? info.GenericTypeArguments.Length
                : info.GenericTypeParameters.Length;
            if (typeof(Nullable<>) == def)
            {
                var type1 = typeGenericTypeArguments[genericTypesCounter++];
                ToCSharpNameEntry(sb, type1);
                sb.Append("?");
                return;
            }

            var n = name.Substring(0, name.IndexOf("`", StringComparison.InvariantCultureIgnoreCase));

            sb.Append(n);
            sb.Append("<");
            for (var i = 0; i < psLength; i++)
            {
                ToCSharpNameEntry(sb, typeGenericTypeArguments[genericTypesCounter++]);
                sb.Append(",");
            }
            sb.Length -= 1;
            sb.Append(">");
            return;
        }
        if (type.IsArray)
        {
            var type1 = type.GetElementType();
            ToCSharpNameEntry(sb, type1);
            sb.Append("[]");
            return;
        }
        sb.Append(name);
    }
}
public静态类TypeFriendlyNameSexture
{
私有静态只读字典类型TofriendlyName=新字典
{
{typeof(string),“string”},
{typeof(object),“object”},
{typeof(bool),“bool”},
{typeof(byte),“byte”},
{typeof(char),“char”},
{typeof(decimal),“decimal”},
{typeof(double),“double”},
{typeof(short),“short”},
{typeof(int),“int”},
{typeof(long),“long”},
{typeof(sbyte),“sbyte”},
{typeof(float),“float”},
{typeof(ushort),“ushort”},
{typeof(uint),“uint”},
{typeof(ulong),“ulong”},
{typeof(void),“void”}
};
公共静态字符串ToCSharpMethodReturnTypeName(此类型)
{
var sb=新的StringWriter();
姓名条目2(sb,类型);
使某人返回字符串();
}
SharpNameEntry2的私有静态无效(文本写入器sb,键入type0)
{
var list=GetContainingTypeList(类型0);
var usedGenericArgumentCounter=0;
HandleNestedLevel(sb,list,0,ref usedGenericArgumentCounter);
foreach(枚举范围(1,list.Count-1)中的var ix)
{
某人写(“.”);
HandleNestedLevel(sb,列表,ix,参考使用NericargumentCounter);
}
}
私有静态void HandleNestedLevel(TextWriter sb、IReadOnlyList、int ix、,
参考int usedGenericArgumentCounter)
{
变量类型=列表[ix];
if(TypeToFriendlyName.TryGetValue(type,out字符串fname))
{
某人写(fname);
返回;
}
if(type.IsGenericParameter)
{
某人写(键入姓名);
返回;
}
如果(键入IsArray)
{
ToCSharpNameEntry2(sb,type.GetElementType());
某人写(“[]”);
返回;
}
if(type.IsGenericType)
{
var innermostType=list[list.Count-1];
var args=list[list.Count-1].GenericTypeArguments;
如果(!type.IsConstructedGenericType)
{
if(innermostType.IsConstructedGenericType)
{
var sname=GetSname(类型);
给某人写信;
某人写(“”);
返回;
}
抛出新的NotImplementedException();
}
if(typeof(Nullable)=type.GetGenericTypeDefinition())
{
tocsharpnamentry2(sb,args[0]);
某人写(“?”);
返回;
}
var cname=GetSname(类型);
某人写(cname);
某人写(“”);
返回;
}
if(类型.IsPointer)
{
姓名条目2(sb,类型);
某人写(“*”);
返回;
}
某人写(键入姓名);
}
私有静态字符串GetSname(类型)
{
var name=type.name;
返回name.Sub
public static class TypeFriendlyNamesExtensions
{
    private static readonly Dictionary<Type, string> TypeToFriendlyName = new Dictionary<Type, string>
    {
        {typeof(string), "string"},
        {typeof(object), "object"},
        {typeof(bool), "bool"},
        {typeof(byte), "byte"},
        {typeof(char), "char"},
        {typeof(decimal), "decimal"},
        {typeof(double), "double"},
        {typeof(short), "short"},
        {typeof(int), "int"},
        {typeof(long), "long"},
        {typeof(sbyte), "sbyte"},
        {typeof(float), "float"},
        {typeof(ushort), "ushort"},
        {typeof(uint), "uint"},
        {typeof(ulong), "ulong"},
        {typeof(void), "void"}
    };

    public static string ToCSharpMethodReturnTypeName(this Type type)
    {
        var sb = new StringWriter();
        ToCSharpNameEntry2(sb, type);
        return sb.ToString();
    }

    private static void ToCSharpNameEntry2(TextWriter sb, Type type0)
    {
        var list = GetContainingTypeList(type0);
        var usedGenericArgumentCounter = 0;

        HandleNestedLevel(sb, list, 0, ref usedGenericArgumentCounter);
        foreach (var ix in Enumerable.Range(1, list.Count - 1))
        {
            sb.Write(".");
            HandleNestedLevel(sb, list, ix, ref usedGenericArgumentCounter);
        }
    }

    private static void HandleNestedLevel(TextWriter sb, IReadOnlyList<Type> list, int ix,
        ref int usedGenericArgumentCounter)
    {
        var type = list[ix];
        if (TypeToFriendlyName.TryGetValue(type, out string fname))
        {
            sb.Write(fname);
            return;
        }
        if (type.IsGenericParameter)
        {
            sb.Write(type.Name);
            return;
        }
        if (type.IsArray)
        {
            ToCSharpNameEntry2(sb, type.GetElementType());
            sb.Write("[]");
            return;
        }

        if (type.IsGenericType)
        {
            var innermostType = list[list.Count - 1];
            var args = list[list.Count - 1].GenericTypeArguments;
            if (!type.IsConstructedGenericType)
            {
                if (innermostType.IsConstructedGenericType)
                {
                    var sname = GetSname(type);
                    sb.Write(sname);
                    sb.Write("<");
                    ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
                    var loopCounter = ((TypeInfo) type).GenericTypeParameters.Length;
                    while (0 < --loopCounter)
                    {
                        sb.Write(",");
                        ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
                    }
                    sb.Write(">");
                    return;
                }
                throw new NotImplementedException();
            }
            if (typeof(Nullable<>) == type.GetGenericTypeDefinition())
            {
                ToCSharpNameEntry2(sb, args[0]);
                sb.Write("?");
                return;
            }
            var cname = GetSname(type);
            sb.Write(cname);
            sb.Write("<");
            ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
            while (usedGenericArgumentCounter < args.Length)
            {
                sb.Write(",");
                ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]);
            }
            sb.Write(">");
            return;
        }
        if (type.IsPointer)
        {
            ToCSharpNameEntry2(sb, type);
            sb.Write("*");
            return;
        }
        sb.Write(type.Name);
    }

    private static string GetSname(Type type)
    {
        var name = type.Name;
        return name.Substring(0, name.IndexOf('`'));
    }

    private static List<Type> GetContainingTypeList(Type type)
    {
        var list = new List<Type> {type};
        var t = type;
        while (t.IsNested)
        {
            t = t.DeclaringType;
            list.Insert(0, t);
        }
        return list;
    }

    private static void ToCSharpNameEntry(StringBuilder sb, Type type)
    {
        var genericTypeArguments = type.GenericTypeArguments;
        var usedGenericTypeCounter = 0;
        ToCSharpNameRecursive(sb, type, genericTypeArguments, ref usedGenericTypeCounter);
    }

    private static void ToCSharpNameRecursive(StringBuilder sb, Type type, IReadOnlyList<Type> genericTypeArguments,
        ref int genericTypesCounter)
    {
        if (TypeToFriendlyName.TryGetValue(type, out string res))
        {
            sb.Append(res);
            return;
        }

        HandleNonPriminiveTypes(sb, type, genericTypeArguments, ref genericTypesCounter);
    }

    private static void HandleNonPriminiveTypes(StringBuilder sb, Type type, IReadOnlyList<Type> typeGenericTypeArguments,
        ref int genericTypesCounter)
    {
        var list = new List<Type>();
        var t = type;
        list.Add(t);
        while (t.IsNested)
        {
            t = t.DeclaringType;
            list.Add(t);
        }
        list.Reverse();
        foreach (var type1 in list)
        {
            HandleNestedLevel(sb, type1, typeGenericTypeArguments, ref genericTypesCounter);
            sb.Append(".");
        }
        sb.Length -= 1;
    }

    private static void HandleNestedLevel(StringBuilder sb, Type type, IReadOnlyList<Type> typeGenericTypeArguments,
        ref int genericTypesCounter)
    {
        var name = type.Name;
        if (type.IsGenericType)
        {
            var info = type.GetTypeInfo();
            var def = info.GetGenericTypeDefinition();
            var psLength = info.IsConstructedGenericType
                ? info.GenericTypeArguments.Length
                : info.GenericTypeParameters.Length;
            if (typeof(Nullable<>) == def)
            {
                var type1 = typeGenericTypeArguments[genericTypesCounter++];
                ToCSharpNameEntry(sb, type1);
                sb.Append("?");
                return;
            }

            var n = name.Substring(0, name.IndexOf("`", StringComparison.InvariantCultureIgnoreCase));

            sb.Append(n);
            sb.Append("<");
            for (var i = 0; i < psLength; i++)
            {
                ToCSharpNameEntry(sb, typeGenericTypeArguments[genericTypesCounter++]);
                sb.Append(",");
            }
            sb.Length -= 1;
            sb.Append(">");
            return;
        }
        if (type.IsArray)
        {
            var type1 = type.GetElementType();
            ToCSharpNameEntry(sb, type1);
            sb.Append("[]");
            return;
        }
        sb.Append(name);
    }
}