Nicholas
Nicholas

Reputation: 19

Invoking an Interface method using reflection

I am using reflection to invoke an Interface method and I have this error message "Object reference not set to an instance of an object." I try using ConstructorInfo too and also have error. Please help.

public class ClassA 
{ 
       private void MethodA(int num, ClassC result)
       {
       } 
}
public interface InterfaceB 
{ 
       ClassC MethodB(int num); 
}
internal class ClassB 
{ 
      public ClassC MethodB(int num)
      {
      } 
}

Type typClassA = Type.GetType("ClassA");
Type typInterfaceB = Type.GetType("InterfaceB");
MethodInfo methodB = typInterfaceB.GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance); // Error lies here
ClassC result = (ClassC) methodB.Invoke(typInterfaceB, new object[]{num});

MethodInfo methodA = typClassA.GetMethod("MethodA", BindingFlags.NonPublic | BindingFlags.Instance);
methodA.Invoke(typClassA, new object[]{num, result});

The actual code for ClassB is not declared as "public ClassB : InterfaceB" but include more classes and ClassB is internal access. See edited codes. Apology for changing the codes so many times as I don't know how to simplify this scenario.

Upvotes: 1

Views: 10490

Answers (7)

Mayank Prajapati
Mayank Prajapati

Reputation: 1

interface IGetNames
{
    string GetFirstName();
    string GetMiddleName();
}
public class GetNames : IGetNames
{
    public string GetFirstName()
    {
        return "First Name";
    }
    public string GetMiddleName()
    {
        return "Middle Name";
    }
}
 static void Main(string[] args)
{
Type _Interface = Type.GetType("ConsoleApplication2.IGetNames");
Type _Class = Type.GetType("ConsoleApplication2.GetNames");
InterfaceMapping GetInterfaceMap = _Class.GetInterfaceMap(_Interface);
MethodInfo methodInfo =  GetInterfaceMap.TargetMethods[0];
object str =  methodInfo.Invoke(Activator.CreateInstance(GetInterfaceMap.TargetType), null);
}

Upvotes: 0

Gun
Gun

Reputation: 1411

You have to give fully qualified name for class . please observe the below example

namespace ConsoleApplication10
{
    interface IA
    {
        void Print();
    }

    class A : IA
    {
        public void Print()
        {
            Console.WriteLine("Hello");
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Type type = Type.GetType("ConsoleApplication10.A");
            type.GetMethod("Print").Invoke(Activator.CreateInstance(type, null), null);
        }
    }
}

Upvotes: 2

Tony
Tony

Reputation: 7445

If you are sure your object has needed method then you can use dynamic and write like this:

var result = (yourObject as dynamic).YourMethod("SomeParam");

Upvotes: 0

Sebastian
Sebastian

Reputation: 8005

C# does not use duck-typing. Therefore in order to actually implement an interface method, you will have to declare that your class implements that interface:

public class ClassB : InterfaceB

There are other problems in your code:

Type typInterfaceB = Type.GetType("InterfaceB"); // unless you have no namespace at all, you need to specify the fully qualified name

// Probably you got an NRE because of above issue here
MethodInfo methodB = typInterfaceB.GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance); 

// this does not work, because the first argument needs to be an instance 
// try "new ClassB()" instead
ClassC result = (ClassC) methodB.Invoke(typInterfaceB, new object[]{num});

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

All your methods are instance (not static) methods, so you have to create instances to call them, and pass these instances to Invoke, for instance:

  // Let's call MethodA from ClassA

  Object instanceA = new ClassA();
  MethodInfo methodA = instanceA.GetType().GetMethod("MethodA", BindingFlags.NonPublic | BindingFlags.Instance);

  // Pay attention to 1st argument - instanceA
  methodA.Invoke(instanceA, new object[]{num, result});  

  ...

  // Since ClassB doesn't implement InterfaceB, the only option 
  // is to call MethodB of ClassB
  Object instanceB = new ClassB();
  MethodInfo methodB = instanceB.GetType().GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance);

  ClassC result = (ClassC) (methodB.Invoke(instanceB, new object[]{num}));

Upvotes: 0

Jcl
Jcl

Reputation: 28272

You are trying to invoke a method on an object of type System.Type, and not on the object that implements that interface.

The first parameter of MethodInfo.Invoke is the instance of the object you want to invoke the method on... you are using an instance of a System.Type object, and not one of ClassA or ClassB

Upvotes: 0

Grundy
Grundy

Reputation: 13381

i don't quite understand what you want, but i think you need something like this

public interface InterfaceB 
{
    int method(int d);
}
public class ClassB:InterfaceB
{
    int a = 10;
    public int method(int d)
    {
        return a + d;
    }
}


var b = new ClassB();
var mi = typeof(ClassB).GetInterface("InterfaceB").GetMethod("method");
var res = mi.Invoke(b, new object[] { 10 }); // res == 20

UPDATE
yet another variant

public interface InterfaceB 
{
    int method(int d);
}
public class ClassB:InterfaceB
{
    int a = 10;
    public int method(int d)
    {
        return a + d;
    }
}


var b = new ClassB();
var mi = typeof(InterfaceB).GetMethod("method");
var res = mi.Invoke(b, new object[] { 10 }); // res == 20

Upvotes: 0

Related Questions