简体   繁体   中英

.NET 2.0: Invoking Methods Using Reflection And Generics Causes Exception

I'm new to Stack Overflow, so forgive me. I've just started transititoning over to C# and I am stuck on a problem.

I am wanting to pass a generic class in and call a method from that class. So, my code looks as such:

public void UpdateRecords<T>(T sender) where T : new() //where T: new() came from Resharper
{
    Type foo = Type.GetType(sender.GetType().ToString());
    object[] userParameters = new object[2];
    userParameters[0] = x;
    userParameters[1] = y;
    sender = new T(); //This was to see if I could solve my exception problem
    MethodInfo populateRecord = foo.GetMethod("MethodInOtherClass");
    populateMethod.Invoke(sender, userParameters);
}

Exception thrown: "Object reference not set to an instance of an object."

Again, I really apologize, as I am nearly brand new to C# and this is the first time I've ever handled reflection and generics. Thank you!

First of all, I would recommend running this code in the debugger and turning one "Break on Exception" to help isolate which line causes the error. This is a useful debugging technique that can help you find these types of problems more quickly in the future. Go to Debug >> Exceptions in VS and check the checkbox for Common Language Runtime Exceptions in the Thrown column.

Now for your issue. It's likely that sender is passed in as null . If so, the line:

Type foo = Type.GetType(sender.GetType().ToString()); 

will throw a NullReferenceException . Instead, you can use:

Type foo = typeof(T); 

which identifies the type of the generic paramter without requiring an instance of it.

Now, without knowing more about what your code is trying to do, it's impossible to say whether instantiating an instance of T is the right thing to do. Just because ReSharper recommends adding where T : new() doesn't mean it's appropriate - unless you know that that's the right behavior .

Finally, I don't know if there is a compelling reason for using reflection to invoke MethodInOtherClass - perhaps there is. But since you're new to C#, I'll mention that if the type T will always be a subclass of some base type A or will always implement some interface I that includes the method you want to call, you can simply apply a generic constraint to let the compiler know this. Then you can call the method without reverting to using reflection:

public void UpdateRecords<T>(T sender) 
   where T : SomeBaseClass_Or_SomeInterface_ThatDefinesMethod
{
  sender = new T();
  sender.MethodInOtherClass( x, y );
}

Much nicer.

One final comment. It's unusual to pass in an argument to a method, and then ignore it completely - only to instantiate an instance within the method. There are cases when it's appropriate - but I tend to view it as a code smell . If possible, I would try to either get rid of the sender argument, or change the code to first test it for null and instantiate only then.

sender.GetType().ToString() returns the type name without the assembly name.

Type.GetType expects a type name with an assembly name (unless the type is in the executing assembly or mscorlib). If the type cannot be found (eg, due to the missing assembly name), it returns a null reference.


Try changing your code to

Type foo = sender.GetType();

or even just

Type foo = typeof(T);

You should just be able to do this to get the type:

Type foo = typeof(T);

You didn't specify where you're getting the NullReferenceException, but I'm wondering if foo is coming back as null...

Either:

  1. sender is null, so sender.GetType() will fail.
  2. foo.GetMethod("MethodInOtherClass") returns null, so populateMethod.Invoke() will fail.
  3. MethodInOtherClass depends on certain preconditions (non-null references), so it will fail when those are absent.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM