Utiliser la réflexion pour définir la valeur d'une propriété à Rien (Null)
Edit: en Fonction de la réponse de LoveMeSomeCode, je crois que ce problème n'apparaît que dans l'VB.Net.
Je suis en train de revenir d'une classe à un état antérieur en enregistrant les anciennes valeurs de la modification des propriétés dans un dictionnaire, et par la réflexion quand j'ai besoin de revenir. Je vais avoir un problème où, si l'ancienne valeur est Rien (null), je reçois une référence nulle exception lorsque vous tentez de définir la propriété. Voici ce que j'ai essayé.
Assumer pour chaque boucle comme ceci:
For Each pair As KeyValuePair(Of String, Object) In myOldValues
...
Next
Méthode 1:
CallByName(Me, pair.Key, CallType.Set, pair.Value)
Méthode 2:
Me.GetType().InvokeMember(pair.Key, Reflection.BindingFlags.SetProperty, Nothing, Me, pair.Value)
Méthode 3:
Dim propInfo As System.Reflection.PropertyInfo = Me.GetType.GetProperty(pair.Key)
propInfo.SetValue(Me, Convert.ChangeType(pair.Value, propInfo.PropertyType), Nothing)
Pour chacune de ces méthodes-je obtenir une référence nulle exception lors de la paire.La valeur est null. Le setter est capable de contenir une valeur null (souvent la propriété est une chaîne). Ce que je fais mal ou comment puis-je contourner cela?
Edit: Chaque méthode échoue si je le passe null directement.
Edit: Ici sont les traces de la pile si ils aider quelqu'un:
Méthode 1
Système.NullReferenceException: la référence d'Objet n'est pas définie à une instance d'un objet.
chez Microsoft.VisualBasic.CompilerServices.Les symboles.Le conteneur.InvokeMethod(Méthode TargetProcedure, Object[] Arguments, Boolean[] CopyBack, BindingFlags Drapeaux)
chez Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateSet(Instance D'Objet De Type Type, String Nomdumembre, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean OptimisticSet, Boolean RValueBase, Appel Appel)
chez Microsoft.VisualBasic.CompilerServices.Versionnées.CallByName(Instance De L'Objet, De La Chaîne De MethodName, Appel UseCallType, Object[] Arguments)
au myProject.Présentateur.CustomerDetailPresenter.RevertCustomer() dans myfile:ligne 378
Méthode 2
Système.De la réflexion.TargetInvocationException: une Exception a été levée par la cible d'un appel. ---> Système.NullReferenceException: la référence d'Objet n'est pas définie à une instance d'un objet.
au myProject.Présentateur.CustomerDetailPresenter.set_City(Chaîne de valeur)
--- Fin de l'exception interne trace de la pile ---
au Système.RuntimeMethodHandle._InvokeMethodFast(Objet cible, Object[] arguments, SignatureStruct& sig, attributs MethodAttributes méthode, Propriétaire typeOwner)
au Système.RuntimeMethodHandle.InvokeMethodFast(Objet cible, Object[] arguments, Signature sig, les attributs MethodAttributes méthode, Propriétaire typeOwner)
au Système.De la réflexion.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder Binder, Object[] paramètres, CultureInfo culture, skipVisibilityChecks Booléens)
au Système.De la réflexion.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder Binder, Object[] paramètres, CultureInfo culture)
au Système.RuntimeType.InvokeMember(String nom, BindingFlags bindingFlags, Binder Binder, de l'Objet cible, Object[] providedArgs, ParameterModifier[] modificateurs, CultureInfo culture, String[] namedParams)
au Système.Type.InvokeMember(String nom, BindingFlags invokeAttr, Binder Binder, de l'Objet cible, Object[] args)
au myProject.Présentateur.CustomerDetailPresenter.RevertCustomer()
Méthode 3
Système.De la réflexion.TargetInvocationException: une Exception a été levée par la cible d'un appel. ---> Système.NullReferenceException: la référence d'Objet n'est pas définie à une instance d'un objet.
au myProject.Présentateur.CustomerDetailPresenter.set_City(Chaîne de valeur)
--- Fin de l'exception interne trace de la pile ---
au Système.RuntimeMethodHandle._InvokeMethodFast(Objet cible, Object[] arguments, SignatureStruct& sig, attributs MethodAttributes méthode, Propriétaire typeOwner)
au Système.RuntimeMethodHandle.InvokeMethodFast(Objet cible, Object[] arguments, Signature sig, les attributs MethodAttributes méthode, Propriétaire typeOwner)
au Système.De la réflexion.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder Binder, Object[] paramètres, CultureInfo culture, skipVisibilityChecks Booléens)
au Système.De la réflexion.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder Binder, Object[] paramètres, CultureInfo culture)
au Système.RuntimeType.InvokeMember(String nom, BindingFlags bindingFlags, Binder Binder, de l'Objet cible, Object[] providedArgs, ParameterModifier[] modificateurs, CultureInfo culture, String[] namedParams)
au Système.Type.InvokeMember(String nom, BindingFlags invokeAttr, Binder Binder, de l'Objet cible, Object[] args)
au myProject.Présentateur.CustomerDetailPresenter.RevertCustomer()
- Êtes-vous sûr que PropertyInfo.SetValue est la méthode de jeter de l'exception?
- Que ou un de ses sous-méthodes, c'est que la ligne.
- De vérifier la trace de pile d'exception; vous devriez être en mesure de discerner la méthode qui est en train de lancer une exception. Si vous ne pouvez pas comprendre cela, essayez d'appeler à la conversion.ChangeType séparément. Mon soupçon est que la méthode est de lancer une exception.
- Merci de m'aider à comprendre cela. J'avais essayé d'avoir le Convertir.ChangeType et tous les autres sous les appels distincts. Ils ont tous travaillé correctement jusqu'à ce que j'ai appelé selon la fonction, essayèrent d'invoquer le setter.
Vous devez vous connecter pour publier un commentaire.
Le fait que vous voyez ce dans les 2e et 3e option traces de pile
me fait penser qu'il y a quelque chose dans votre CustomerDetailPresenter.Propriété de la ville de poseur qui n'est pas de la manipulation de la valeur null. Qu'est-ce que la mise en œuvre de votre propriété setter? C'est que tout de validation ou de vérification du code qui pourrait être défectueux?
Mise à jour 03-24-2009:
Un test rapide en VB, ce code fonctionne comme prévu. J'ai essayé de capturer le scénario que vous décrivez.
Ma classe de test qui a la propriété la valeur (en partie):
J'ai créé un PropertyState classe qui va contenir le nom de la propriété, la valeur et le type. Et le code de la propriété de manière dynamique est:
J'ai utilisé deux surcharges de la méthode SetValue, j'ai constaté que pas explicitement réglage de la BindingFlags peut provoquer la réflexion questions à la fois. Toutefois, dans ce cas, les deux overlaods beau travail.
Donc, je regarde en arrière à la trace de la pile où vous avez posté votre question:
le fait que le set_City() setter est ce qui est en train de jeter l'exception indique que la méthode est trouvé et l'a appelé avec succès. La valeur null(nothing) la valeur est transmise sous la forme demandée. Donc, le bug n'est pas dans la réflexion, mais dans ce qui se passe comme une conséquence de la propriété de poseur d'être appelé. Vous avez probablement déjà essayé cela, mais la définition d'un point de rupture dans l'incubateur ou la mise à l'IDE d'arrêt sur toutes les exceptions gérées pour voir si vous pouvez capturer la cause réelle? Ou est l'état de la stockées info propriété de ce qui est attendu? Le nom, le type et la valeur de tous synchronisés?
Espère que cette aide.
Dans
SetValue
,Convert.ChangeType
appelsIConvertible
méthodes surpair.Value
, sûrement, ils échouer lorsque vous essayez de les appeler surnull
instance.Vérifier
pair.Value
pour nullness et de passer un explicitenull
si c'est le cas.InvokeMember
attend un tableau 5ème argument. Essayez:Bien, c'est le C# au lieu de VB.NET mais cela semble fonctionner:
de sorte que vous pouvez définir les propriétés et d'appel(), et ils seront enregistrées dans le dictionnaire. Ensuite, vous pouvez les modifier et de les appeler le Rappel (le) et ils seront restaurés. Il semble que le travail sera nulle pour les chaînes de caractères au moins. Il semble comme une bonne série de choses à mettre dans une classe de base.