Search code examples
c#reflectiondependency-injectioninterfaceinvoke

How to invoke base-class method of injected object?


(I couldn't come up with a succinct title for this question that didn't drag on.)

I have a base class that has one public method:

public class MyBaseClass
{
    public void MyBaseMethod()
    {
        // Here is where the functionality will go, that is described below.
    }
}

I have another class, derived from my base class, that contains injected objects that also derive from MyBaseClass:

public class MyWorkingClass : MyBaseClass
{
    // All of these objects also derive from MyBaseClass.
    private readonly IClassOne _classOne;
    private readonly IClassTwo _classTwo;
    private readonly IClassThree _classThree;

    public MyWorkingClass(
        IClassOne classOne,
        IClassTwo classTwo,
        IClassThree classThree)
    {
        _classOne = classOne;
        _classTwo = classTwo;
        _classThree = classThree;
    }

    public SomeMethod()
    {
        // Stuff goes here.

        // Call base method here.
        MyBaseMethod();
    }
}

What I want to happen is that the call to MyBaseMethod will collect all of the fields declared in the class. For each field, get its instance and call its own MyBaseMethod.

I can get all of the fields in a class instance:

var fields = GetType()
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
    .ToList();

For each field in the list, I can get its field type, instance and its own declared methods:

foreach (var field in fields)
{
    var fieldType = field.FieldType;

    var fieldInstance = field
        .GetValue(this);

    var methods = fieldType
        .GetMethods();
}

My problem is that my base-class method, MyBaseMethod, is not included in the list of methods. I have also tried GetRuntimeMethods(), but it is not included there either.

If I could get access to the base-class method, then I could invoke it:

var methodInfo = fieldType
    .GetMethod('MyBaseMethod');

methodInfo
    .Invoke(fieldInstance, null);

Question: How can I manage to invoke my base-class method in each field instance, given that its type is listed as being an interface?

Thanks.


Solution

  • So the problem here, is you need to use the actual instance from the field

    E.g

    var methods = fieldInstance
        .GetType()
        .GetRuntimeMethods();
    

    Example

    Given some contrived set of classes and interfaces (trying to replicate what you have described)

    public interface ITest { }
    
    public class SomeOtherClass : MyBaseClass, ITest { }
    
    public class MyWorkingClass : MyBaseClass, ITest
    {
       private readonly ITest _test;
    
       public MyWorkingClass(ITest test)
       {
          _test = test;
       }
    
       public void SomeMethod()
       {    
          MyBaseMethod(); 
       }
    }
    
    public class MyBaseClass
    {
       public void MyBaseMethod()
       {
          var fields = GetType()
             .GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
             .ToList();
    
          foreach (var field in fields)
          {
             var fieldType = field.FieldType;
    
             var fieldInstance = field
                .GetValue(this);
    
             if (fieldInstance == null)
                return;
             var methods = fieldInstance
                .GetType()
                .GetRuntimeMethods();
    
             foreach (var item in methods)
                Console.WriteLine(item.Name);
    
          }  
       }
    }
    

    Usage

    var asd = new MyWorkingClass(new SomeOtherClass());
    asd.SomeMethod();
    

    Output

    MyBaseMethod
    GetType
    MemberwiseClone
    Finalize
    ToString
    Equals
    GetHashCode
    

    The words most convoluted example