7
votes

vérifier à l'avance si `system.activator.createinstance (de t) échouera

J'ai un type (humain) et je veux savoir si je pouvais faire system.activator.createinstance (de l'homme) () code>. Donc, fondamentalement, je veux vérifier si l'homme a un constructeur de paramètres publics / ou un constructeur public avec des paramètres facultatifs permettant d'appeler nouvel humain code> sans donner des arguments.

est-il possible de vérifier à l'avance Si System.Activator.CreateInstance (de T) code> échouera? (Je veux dire autre que d'envelopper l'énoncé System.ACtivator.CreateInstance (de l'homme) () code> dans une prise d'essai bien sûr ..) p>

J'ai essayé cela mais ça ne 'T Travailler: P>

Option Strict On : Option Explicit On
Module Test
    Public Class Human
        Public Sub New(Optional ByVal a As Integer = 1)

        End Sub
    End Class
    Public Sub Main()
        Dim c = GetType(Human).GetConstructor(System.Type.EmptyTypes)
        MsgBox(c Is Nothing)
    End Sub
End Module


2 commentaires

Remarque, que cela ne fonctionnera pas / ne fonctionnera jamais de la case pour les constructeurs "avec seulement des arguments facultatifs". Voir ma réponse ci-dessous pour plus de détails et de fond.


Dupliqué possible de Comment puis-je vérifier si un type fournit un constructeur sans paramètre?


4 Réponses :


4
votes

Vous pouvez vérifier et vous assurer que votre type humain code> a un constructeur sans paramètre accessible. La meilleure façon de faire est de créer une méthode générique et d'ajouter une contrainte où T: nouveau () code>

edit: p>

Vous pouvez vérifier manuellement le constructeur sans paramètre comme celui-ci p >

if(typeof(Human).GetType().GetConstructor(Type.EmptyTypes) !=null)
{
  ...      
}


3 commentaires

Je sais à propos de cette contrainte où T: Nouveau () Toutefois, j'ai besoin de t pour prendre en charge les deux types qui ont des contraintes nouveaux () et types qui n'ont pas cette contrainte


@Pacerier Les paramètres facultatifs le rend délicat. Mais @magnus Réponse a adressé cette zone.


Extra gettype () ne doit pas être utilisé comme type typeof (humain) obtient déjà le type. (ou simplement utiliser gettype () au lieu de typeof () )



1
votes

J'ai créé une application de console rapide à l'aide de la réflexion pour tester les constructeurs de paramètres sur des types. Est-ce ce dont vous avez besoin? XXX


0 commentaires

9
votes

Pour vérifier si le constructeur est vide ou que tous les paramètres sont facultatifs:

var hasEmptyOrDefaultConstr = 
  typeof(Human).GetConstructor(Type.EmptyTypes) != null || 
  typeof(Human).GetConstructors(BindingFlags.Instance | BindingFlags.Public)
    .Any (x => x.GetParameters().All (p => p.IsOptional));


6 commentaires

Cela ne fonctionne pas si j'ai un Sous-nouveau privé il me dit que c'est vrai. Mais si je fais `system.activator.createinstance (de l'homme) ()` Je vais avoir une exception bien sûr!


OK, j'ai mis à jour la réponse pour exclure des constructeurs non publics et statiques


ok cool j'ai installé avec ceci: dim is_activatable = gettype (humain) .betconstructeurs (système.reflection.bindingflag s.instance ou system.reflet.bindingflags.pindingflags.public). Nan (fonction (c) c.geparamètres .All (fonction (p) p.isoptional))


BTW n'est-il pas bizarre qu'il n'y a pas de fonction intégrée isactivatable ?


Je peux voir comment cela serait utile.


+1: merci. Comme la requête LINQ pour vérifier un constructeur avec tous les arguments facultatifs



3
votes

Veuillez noter que activator.createinstance () code> ou activator.createInstance (type) code> fonctionnera uniquement avec des constructeurs sans paramètre. Un constructeur avec uniquement des arguments facultatifs est pas em> paramètre sans paramètre dans ce sens.

Les paramètres facultatifs (ou arguments) sont résolus par le compilateur C # sur le site d'appel em>. Cependant, il n'y a pas de compilateur impliqué de manière à apposer le constructeur à l'aide de la réflexion. P>

Si vous utilisez le code suivant, vous obtiendrez un mancheMethodException code> dire qu'il n'y a pas de Constructeur sans paramètre défini: p> xxx pré>

En d'autres termes Les arguments facultatifs sont une chose compilatrice, pas une chose CLR. P>

Pour plus d'informations sur "Cas d'angle avec facultatif Arguments "Voir cette récente série de blogs d'Eric Lippert: P>

http://ericlippert.com/2011/05/09/Optional-argument-corner-cases-par-one/ P>

Ayant cela dit, vous pourriez être Capable d'en quelque sorte répliquer le comportement souhaité en utilisant une réflexion plus poussée et créant manuellement les paramètres requis pour l'appel du constructeur. Le compilateur placera certains attributs à l'intérieur de l'assemblage que vous pourriez utiliser à cet effet, je suppose. P>

Exemple: P>

public class Foo
{
    public Foo([Optional, DefaultParameterValue(5)] int optional)
    {
        Console.WriteLine("Constructed");
    }
}


4 commentaires

BTW Comment traduisons-nous votre dernier paragraphe en VB?


@Pacerier: Je ne suis pas tout à fait sûr de quoi vous parlez exactement, mais les attributs placés dans le code par le compilateur sont les mêmes pour C # et VB.NET, c'est-à-dire que les deux compilateurs semblent générer le même code à cet égard.


@ Christian.k je veux dire que je ne sais pas où mettre la ligne [facultatif, defaultParameValue (5)] . Cela ne compile pas pour moi: Sub NOUVEAU PUBLIC PUBLIC PUBLIC ([[[[Facultatif, DefaultParameValue (5)] BYVAL X en tant qu'integer) Classe de sous-fin entier)


@Pacerier Vous ne le mettez pas là-bas, cela fait votre compilateur (vb.net ou c #). Vous devez lire eux (en utilisant la réflexion). Pour rester dans l'esprit des autres réponses, vous pouvez faire quelque chose comme ceci: (1) Déterminez si vous avez un véritable constructeur sans paramètre, si oui, faites comme les autres suggérées. (2) Si vous avez un constructeur dans lequel tous les paramattres ont des valeurs par défaut (d'où les attributs indiqués dans "l'exemple" de ma réponse), vous utilisez la réflexion pour obtenir les valeurs et créer un objet approprié [] de le transmettre à l'activateur .CreateInstance-surcharge pour constructeurs sans paramètre.