74 votes

Comment tester si un type est anonyme ?

J'ai la méthode suivante qui sérialise un objet dans une balise HTML. Je ne veux cependant le faire que si le type n'est pas anonyme.

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

Quelqu'un peut-il me montrer comment y parvenir ?

Merci

77voto

Sunny Points 3189

Desde 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 :
Un autre lien avec la méthode d'extension : Déterminer si un type est un type anonyme

2 votes

2 votes

Malheureusement, c'est faux pour new{}.GetType() Mais je pense && type.IsGenericType peut être retiré sans problème.

2 votes

On dirait que vous avez besoin (type.Name.Contains("AnonymousType") || type.Name.Contains("AnonType")) pour être compatible avec le Mono. Source : Méthode d'extension de NancyFx

22voto

BjarkeCK Points 1589

Rapide et sale :

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

5 votes

Je suis très tenté de cliquer sur +1. Ne doit pas cliquer ! xD

1 votes

Sale et lent malheureusement.

2 votes

J'aime bien celle-ci parce qu'elle est très simple et ne devrait être une erreur que dans le cas pathologique où quelqu'un a créé une classe avec "A".

15voto

DalSoft Points 1827

Vous pouvez simplement vérifier si l'espace de nom est nul.

public static bool IsAnonymousType(this object instance)
{

    if (instance==null)
        return false;

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

1 votes

Cela fonctionne-t-il pour le mono ?

0 votes

Il existe des cas où cela n'est pas vrai. Je ne suis pas sûr de tous les cas où cela échoue, mais un exemple est celui où une expression lambda est utilisée dans une méthode concrète protégée d'une classe abstraite avec des paramètres génériques. Je suis sûr qu'il existe des cas plus simples qui échoueraient également.

3 votes

@DalSoft Placez n'importe quelle classe en dehors d'un espace de nom et vous voilà parti, ce qui est en fait courant dans certains frameworks.

7voto

Konstantin Isaev Points 167

Eh bien, aujourd'hui compiier génère des types anonymes comme des classes génériques ET scellées. Une combinaison paradoxale puisque la spécialisation d'une classe générique est une sorte d'héritage, n'est-ce pas ? Vous pouvez donc vérifier cela : 1. Est-ce un type générique ? Oui => 2) sa définition est-elle scellée && non publique ? Oui => 3) sa définition possède-t-elle l'attribut CompilerGeneratedAttribute ? Je suppose que si ces 3 critères sont vrais ensemble, nous avons un type anonyme... Et bien... Il y a un problème avec TOUTES les méthodes décrites - ce sont des aspects d'utilisation qui peuvent changer dans les prochaines versions de .NET et il en sera ainsi jusqu'à ce que Microsoft ajoute la propriété booléenne IsAnonymous à la classe Type. J'espère que cela arrivera avant que nous mourions tous... Jusqu'à ce jour, il peut être vérifié comme suit :

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

6voto

Catalin DICU Points 2785

Vérifiez si CompilerGeneratedAttribute y DebuggerDisplayAttribute.Type

voici le code généré par le compilateur pour un type anormal

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

3 votes

Ne fonctionne que lors de la compilation en mode débogage.

0 votes

Fonctionne aussi en mode release ! var anonType = new {a = 1, b = 2}.GetType() ; anonType.CustomAttributes.Select(e => e.AttributeType).Should().Contain(typeof(CompilerGeneratedAttribute)) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X