代码之家  ›  专栏  ›  技术社区  ›  Entity

C获取通用类型名

  •  35
  • Entity  · 技术社区  · 14 年前

    我需要一些方法来获得一个类型的名称,当 type.IsGenericType = true

        Type t = typeof(List<String>);
        MessageBox.Show( ..?.. );
    

    我想要的是弹出一个信息框 List 显示。。。我该怎么做?

    7 回复  |  直到 14 年前
        1
  •  32
  •   LukeH    14 年前
    Type t = ...;
    
    if (t.IsGenericType)
    {
        Type g = t.GetGenericTypeDefinition();
    
        MessageBox.Show(g.Name);                                // displays "List`1"
    
        MessageBox.Show(g.Name.Remove(g.Name.IndexOf('`')));    // displays "List"
    }
    
        2
  •  52
  •   yoyo    7 年前

    您可以实现一个扩展方法来获取类型的“友好名称”,如下所示:

    public static class TypeNameExtensions
    {
        public static string GetFriendlyName(this Type type)
        {
            string friendlyName = type.Name;
            if (type.IsGenericType)
            {
                int iBacktick = friendlyName.IndexOf('`');
                if (iBacktick > 0)
                {
                    friendlyName = friendlyName.Remove(iBacktick);
                }
                friendlyName += "<";
                Type[] typeParameters = type.GetGenericArguments();
                for (int i = 0; i < typeParameters.Length; ++i)
                {
                    string typeParamName = GetFriendlyName(typeParameters[i]);
                    friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
                }
                friendlyName += ">";
            }
    
            return friendlyName;
        }
    }
    

    在您的项目中,您现在可以说:

    MessageBox.Show(t.GetFriendlyName());
    

    它将显示“list<string>”。

    我知道OP没有要求泛型类型参数,但我更喜欢这样。;-)

    命名空间, standard aliases for built-in types ,并将StringBuilder作为练习留给读者。;-)

        3
  •  16
  •   Humberto    9 年前

    我接受Yoyo的方法。确保基元、处理数组的名称更友好,并递归以处理嵌套的泛型。还有单元测试。

        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 GetFriendlyName(this Type type)
        {
            string friendlyName;
            if (_typeToFriendlyName.TryGetValue(type, out friendlyName))
            {
                return friendlyName;
            }
    
            friendlyName = type.Name;
            if (type.IsGenericType)
            {
                int backtick = friendlyName.IndexOf('`');
                if (backtick > 0)
                {
                    friendlyName = friendlyName.Remove(backtick);
                }
                friendlyName += "<";
                Type[] typeParameters = type.GetGenericArguments();
                for (int i = 0; i < typeParameters.Length; i++)
                {
                    string typeParamName = typeParameters[i].GetFriendlyName();
                    friendlyName += (i == 0 ? typeParamName : ", " + typeParamName);
                }
                friendlyName += ">";
            }
    
            if (type.IsArray)
            {
                return type.GetElementType().GetFriendlyName() + "[]";
            }
    
            return friendlyName;
        }
    
    [TestFixture]
    public class TypeHelperTest
    {
        [Test]
        public void TestGetFriendlyName()
        {
            Assert.AreEqual("string", typeof(string).FriendlyName());
            Assert.AreEqual("int[]", typeof(int[]).FriendlyName());
            Assert.AreEqual("int[][]", typeof(int[][]).FriendlyName());
            Assert.AreEqual("KeyValuePair<int, string>", typeof(KeyValuePair<int, string>).FriendlyName());
            Assert.AreEqual("Tuple<int, string>", typeof(Tuple<int, string>).FriendlyName());
            Assert.AreEqual("Tuple<KeyValuePair<object, long>, string>", typeof(Tuple<KeyValuePair<object, long>, string>).FriendlyName());
            Assert.AreEqual("List<Tuple<int, string>>", typeof(List<Tuple<int, string>>).FriendlyName());
            Assert.AreEqual("Tuple<short[], string>", typeof(Tuple<short[], string>).FriendlyName());
        }
    }
    
        4
  •  8
  •   Alex Wiese    11 年前

    假设你只是想看看 List<T> 而不是 List<string> 你需要做的是:

    MessageBox.Show(t.GetGenericTypeDefinition().FullName)
    

    http://msdn.microsoft.com/en-us/library/system.type.getgenerictypedefinition.aspx

        5
  •  6
  •   Ali    9 年前
    public static class TypeNameExtensions
    {
        public static string GetFriendlyName(this Type type)
        {
            var friendlyName = type.Name;
            if (!type.IsGenericType) return friendlyName;
    
            var iBacktick = friendlyName.IndexOf('`');
            if (iBacktick > 0) friendlyName = friendlyName.Remove(iBacktick);
    
            var genericParameters = type.GetGenericArguments().Select(x => x.GetFriendlyName());
            friendlyName += "<" + string.Join(", ", genericParameters) + ">";
    
            return friendlyName;
        }
    }
    
        6
  •  5
  •   Yepeekai    7 年前

    这是我的看法。我没有做任何检查,因为我所看到的,总是在那里。如果你愿意的话,你可以添加它,但我喜欢保持简单。

    public static string GetFriendlyName(this Type type)
    {
        if (type.IsGenericType)
        {
            var name = type.Name.Substring(0, type.Name.IndexOf('`'));
            var types = string.Join(",", type.GetGenericArguments().Select(GetFriendlyName));
            return $"{name}<{types}>";
        }
        else
        {
            return type.Name;
        }
    }
    
        7
  •  3
  •   Thomas Haller    10 年前

    我已经改进了Yoyos版本,以便在代码生成中使用。 请注意,现在引用的所有类型都是完全限定的=>全局::System.String。

                public static string GetFriendlyTypeName(Type type)
                {
                    string friendlyName = type.Name;
                    if (type.IsGenericType)
                    {
                        int iBacktick = friendlyName.IndexOf('`');
                        if (iBacktick > 0)
                        {
                            friendlyName = friendlyName.Remove(iBacktick);
                        }
                        friendlyName += "<";
                        Type[] typeParameters = type.GetGenericArguments();
                        for (int i = 0; i < typeParameters.Length; ++i)
                        {
                            string typeParamName = GetFriendlyTypeName(typeParameters[i]);
                            friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
                        }
                        friendlyName += ">";
                        friendlyName = "global::" + type.Namespace + "." + friendlyName;
                    }
                    else
                    {
                        friendlyName = "global::" + type.FullName;
                    }
    
                    return friendlyName.Replace('+', '.');
                }