Home > Back-end >  How do I use reflection to execute an explicitly-implemented static abstract method
How do I use reflection to execute an explicitly-implemented static abstract method

Time:01-19

Given the following interface that forces classes to implement a static method...

public interface IMyInterface<T>
{
    static abstract int GetNumber();
}

And two classes that both have two implementations of IMyInterfacee<T>

public class MyClass1 : IMyInterface<Company>, IMyInterface<Person>
{
    static int IMyInterface<Company>.GetNumber() => 1;
    static int IMyInterface<Person>.GetNumber() => 2;
}

public class MyClass2 : IMyInterface<Company>, IMyInterface<Person>
{
    static int IMyInterface<Company>.GetNumber() => 3;
    static int IMyInterface<Person>.GetNumber() => 4;
}

When I have a method in a consuming class like this

public int GetNumbers(Type classType, Type genericType)
{
  Type interfaceType = typeof(IMyInterface<>).MakeGenericType(genericType);
  return ??????
}

How would I implement GetNumbers so that I can call it like so

GetNumbers(typeof(MyClass1), typeof(Company)); // returns 1
GetNumbers(typeof(MyClass1), typeof(Person)); // returns 2
GetNumbers(typeof(MyClass2), typeof(Company)); // returns 3
GetNumbers(typeof(MyClass2), typeof(Person)); // returns 3

CodePudding user response:

You can use interface mapping (Type.GetInterfaceMap) to find the method which implements the interface:

int GetNumbers(Type classType, Type genericType)
{
    Type interfaceType = typeof(IMyInterface<>).MakeGenericType(genericType);

    // todo - check that class implements interface
    var interfaceMapping = classType.GetInterfaceMap(interfaceType);

    MethodInfo? methodInfo = null;
    for (int i = 0; i < interfaceMapping.InterfaceMethods.Length; i  )
    {
        var sourceMethod = interfaceMapping.InterfaceMethods[i];
        // simple predicate to find by name
        // possibly check that parameters are empty and return type is int
        if (sourceMethod.Name.Equals(nameof(IMyInterface<object>.GetNumber), StringComparison.Ordinal))
        {
            methodInfo = interfaceMapping.TargetMethods[i];
            break;
        }
    }

    if (methodInfo is null)
    {
        throw new Exception("Should not happen");
    }

    return (int)methodInfo.Invoke(null, null);
}
  •  Tags:  
  • c#
  • Related