如何测试一个类型是否为匿名类型?

74

我有以下方法可以将一个对象序列化为HTML标签。但是,如果该对象是匿名类型,则我只想这样做。

private void MergeTypeDataToTag(object typeData)
{
    if (typeData != null)
    {
        Type elementType = typeData.GetType();

        if (/* elementType != AnonymousType */)
        {
            _tag.Attributes.Add("class", elementType.Name);    
        }

        // do some more stuff
    }
}

有人能展示给我如何实现这个吗?

谢谢

5个回答

78

来自http://www.liensberger.it/web/blog/?p=191

private static bool CheckIfAnonymousType(Type type)
{
    if (type == null)
        throw new ArgumentNullException("type");

    // HACK: The only way to detect anonymous types right now.
    return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
        && type.IsGenericType && type.Name.Contains("AnonymousType")
        && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
        && type.Attributes.HasFlag(TypeAttributes.NotPublic);
}

编辑:
另一个具有扩展方法的链接:确定类型是否为匿名类型


2
检查匿名类型 - serhio
2
遗憾的是,对于 new{}.GetType() 来说这是错误的。但我认为 && type.IsGenericType 可以安全地删除。 - Lars Corneliussen
2
看起来你需要 (type.Name.Contains("AnonymousType") || type.Name.Contains("AnonType")) 才能兼容Mono。来源: NancyFx扩展方法 - Justin Caldicott
2
现在已经是2016年了,有人知道是否有一些新的可能实现吗? - Francesco Bonizzi
3
(type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic这句话的意思是:检查类型的访问权限是否为非公开,但实际上TypeAttributes.NotPublic的值为0,因此该检查总是为真。正确的检查应该使用TypeAttributes.Public来判断类型是否为公开访问。 - user743382

22

快速且简单:

if(obj.GetType().Name.Contains("AnonymousType"))

5
我非常想点赞。不过不能点!!xD - Davi Fiamenghi
1
脏且慢,不幸的是。 - Serguei Fedorov
4
我喜欢这个方法,因为它非常简单,只有在极端情况下出错,即某人创建了一个名称中带有“AnonymousType”的类,但该对象实际上不是匿名类型。那些假设的人应该受到惩罚。 - Daniel Williams

16

您只需检查命名空间是否为null。

public static bool IsAnonymousType(this object instance)
{

    if (instance==null)
        return false;

    return instance.GetType().Namespace == null;
}

1
这适用于Mono吗? - albertjan
3
在任何命名空间之外放置一个类即可,这在一些框架中是很常见的做法。 - BjarkeCK
@DalSoft 好耶^^ 我想知道在 Mono 中是否也是这种情况。正在测试... - BjarkeCK
1
@DalSoft 哦,你犯了一个小错误。你测试了 typeof(Type) 的命名空间是否为空。已修复:http://rextester.com/BOL44171(true,true) - BjarkeCK
抱歉,昨天情绪有些低落 - 很高兴知道这一点。因此,在使用它方面,我想对于大多数用例来说只需要几行代码,或者如果您需要捕获所有情况,则可以选择更详细的解决方案。 - DalSoft
显示剩余2条评论

8
今天,编译器将匿名类型生成为既是泛型又是密封类。这是一种矛盾的组合,因为泛型类的特化是一种继承,不是吗? 所以你可以检查以下内容: 1. 这是一个泛型类型吗? 是 => 2)它的定义是否为sealed且不公开? 是 => 3)它的定义是否带有CompilerGeneratedAttribute属性? 我猜,如果这三个条件都同时成立,我们就拥有了一个匿名类型… 嗯…所述的任何方法都存在问题 - 它们使用可能会在 .NET 的下个版本中发生变化的方面,这将持续到 Microsoft 在 Type 类中添加 IsAnonymous 布尔属性之前。希望这会在我们所有人死亡之前发生… 在那一天之前,可以这样检查:
using System.Runtime.CompilerServices;
using System.Reflection;

public static class AnonymousTypesSupport
{
    public static bool IsAnonymous(this Type type)
    {
        if (type.IsGenericType)
        {
            var d = type.GetGenericTypeDefinition();
            if (d.IsClass && d.IsSealed && d.Attributes.HasFlag(TypeAttributes.NotPublic))
            {
                var attributes = d.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);
                if (attributes != null && attributes.Length > 0)
                {
                    //WOW! We have an anonymous type!!!
                    return true;
                }
            }
        }
        return false;
    }

    public static bool IsAnonymousType<T>(this T instance)
    {
        return IsAnonymous(instance.GetType());
    }
}

6

检查 CompilerGeneratedAttributeDebuggerDisplayAttribute.Type

这里是编译器为匿名类型生成的代码

[CompilerGenerated, DebuggerDisplay(@"\{ a = {a} }", Type="<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<<a>j__TPar>
{
...
}

3
仅在调试模式下编译时有效。 - João Bragança
也适用于发布模式! var anonType = new {a = 1, b = 2}.GetType(); anonType.CustomAttributes.Select(e => e.AttributeType).Should().Contain(typeof(CompilerGeneratedAttribute)); - Ibrahim ben Salah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接