74

I have the following method which serialises an object to a HTML tag. I only want to do this though if the type isn't Anonymous.

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
    }
}

Can somebody show me how to achieve this?

Thanks

abatishchev
  • 98,240
  • 88
  • 296
  • 433
DaveDev
  • 41,155
  • 72
  • 223
  • 385

5 Answers5

78

From 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);
}

EDIT:
Another link with extension method: Determining whether a Type is an Anonymous Type

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Sunny
  • 6,286
  • 2
  • 25
  • 27
  • 2
    source from http://jclaes.blogspot.com/2011/05/checking-for-anonymous-types.html – serhio Sep 06 '11 at 12:28
  • 2
    Sadly this is false for `new{}.GetType()` But i think `&& type.IsGenericType` can savely be removed. – Lars Corneliussen Sep 14 '11 at 16:15
  • 2
    Looks like you need `(type.Name.Contains("AnonymousType") || type.Name.Contains("AnonType"))` to be compatible with Mono. Source: [NancyFx extension method](https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ViewEngines/Extensions.cs) – Justin Caldicott Jul 24 '15 at 10:33
  • 2
    Now it's 2016, do someone know if is there some new possible implementation? – Francesco Bonizzi Dec 02 '16 at 11:42
  • 3
    `(type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic` is trivially always true, because `TypeAttributes.NotPublic == 0`. This check should be done with `TypeAttributes.Public`. –  Sep 21 '17 at 12:25
23

Quick and dirty:

if(obj.GetType().Name.Contains("AnonymousType"))
BjarkeCK
  • 5,694
  • 5
  • 41
  • 59
15

You can just check if the namespace is null.

public static bool IsAnonymousType(this object instance)
{

    if (instance==null)
        return false;

    return instance.GetType().Namespace == null;
}
DalSoft
  • 10,673
  • 3
  • 42
  • 55
  • 1
    does this work for mono? – albertjan May 23 '13 at 09:38
  • There are cases where this does not hold true. I'm not sure of all cases where this fails, but one example is where a lambda expression is used within a protected concrete method of an abstract class with generic parameters. I'm sure there are simpler cases that would also fail. – Nathan May 06 '14 at 21:32
  • 3
    @DalSoft Place any class outside a namespace and there you go, which is actually common in some frameworks. – BjarkeCK May 31 '17 at 13:54
  • @DalSoft Woot^^ I wonder if this is the case in mono as well. Testing.. – BjarkeCK May 31 '17 at 20:00
  • @DalSoft It's null in Mono 2.0 – BjarkeCK May 31 '17 at 20:03
  • 1
    @DalSoft Ah, you made a woops. You tested if typeof(Type)'s namespace was null. Fixed: http://rextester.com/BOL44171 (true, true) – BjarkeCK May 31 '17 at 20:09
  • Woops sorry was having a bad day yesterday - good to know. So in terms of using this then I guess it's a couple of lines for most use cases, or pick a more verbose solution if you need to catch all cases. – DalSoft Jun 01 '17 at 08:43
8

Well, today compiier generates anonymous types as generic AND sealed classes. A paradoxal combination since specialization of a generic class is a kind of inheritance, isn't? So you can check for this: 1. Is this a generic type? Yes => 2) is its definition sealed && not public? Yes => 3) is its definition has CompilerGeneratedAttribute attribute? I guess, if these 3 criteria are true together, we have an anonymous type... Well... There is a problem with ANY of methods described - they are use aspects that may change in next versions of .NET and it will be so until Microsoft will add IsAnonymous boolean property to Type class. Hope it will happen before we all die... Until that day, it can be checked like so:

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());
    }
}
Konstantin Isaev
  • 642
  • 8
  • 14
6

Check for CompilerGeneratedAttribute and DebuggerDisplayAttribute.Type

here is the code generated by the compiler for an anomymous type

[CompilerGenerated, DebuggerDisplay(@"\{ a = {a} }", Type="<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<<a>j__TPar>
{
...
}
Catalin DICU
  • 4,610
  • 5
  • 34
  • 47