Edit: Based on the answer from LoveMeSomeCode, I believe this issue only appears in VB.Net.
I'm trying to revert a class to a previous state by saving the old values of changed properties in a dictionary and setting them via reflection when I need to revert. I'm having a problem where if the old value is Nothing (null) I get a null reference exception when trying to set the property. Here's what I've tried.
Assume a for each loop like this:
For Each pair As KeyValuePair(Of String, Object) In myOldValues
...
Next
Method 1:
CallByName(Me, pair.Key, CallType.Set, pair.Value)
Method 2:
Me.GetType().InvokeMember(pair.Key, Reflection.BindingFlags.SetProperty, Nothing, Me, pair.Value)
Method 3:
Dim propInfo As System.Reflection.PropertyInfo = Me.GetType.GetProperty(pair.Key)
propInfo.SetValue(Me, Convert.ChangeType(pair.Value, propInfo.PropertyType), Nothing)
For each of these methods I get a null reference exception when pair.Value is null. The setter is capable of holding a null value (frequently the property is a string). What am I doing wrong or how can I work around it?
Edit: Each method fails if I pass it null directly as well.
Edit: Here are the stack traces if they help anyone:
Method 1 System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.VisualBasic.CompilerServices.Symbols.Container.InvokeMethod(Method TargetProcedure, Object[] Arguments, Boolean[] CopyBack, BindingFlags Flags) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateSet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean OptimisticSet, Boolean RValueBase, CallType CallType) at Microsoft.VisualBasic.CompilerServices.Versioned.CallByName(Object Instance, String MethodName, CallType UseCallType, Object[] Arguments) at myProject.Presenter.CustomerDetailPresenter.RevertCustomer() in myfile:line 378
Method 2 System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at myProject.Presenter.CustomerDetailPresenter.set_City(String value) --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args) at myProject.Presenter.CustomerDetailPresenter.RevertCustomer()
Method 3 System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at myProject.Presenter.CustomerDetailPresenter.set_City(String value) --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args) at myProject.Presenter.CustomerDetailPresenter.RevertCustomer()