Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check whether one .NET type implements certain .NET interface abstractly?

I have a type and an interface and I need to verify that the type implements the interface abstractly.

I have set to write a brute force code using Reflection and it is pretty ugly.

I am wondering if there is a better way than the brute force implementation I am doing now.

Any ideas?

Thanks.

EDIT

Have not checked the implementation yet, but the brute force draft code looks like this:

  public static bool IsAbstractInterfaceImplementation(Type someType, Type someInterface)
  {
    if (!someInterface.IsAssignableFrom(someType))
    {
      return false;
    }

    if (!someType.IsAbstract)
    {
      return false;
    }

    var m_interfaceMemberNames = someInterface.GetMembers().Select(m => m.Name).ToList();
    // Make sure every interface member implementation is abstract.
    foreach (var typeMember in someType.FindMembers(MemberTypes.Event | MemberTypes.Property | MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance, null, null))
    {
      if (m_interfaceMemberNames.Contains(typeMember.Name))
      {
        MethodInfo method;
        // Make sure the ancestor member is abstract.
        switch (typeMember.MemberType)
        {
        case MemberTypes.Event:
          if (!IsAbstractImplementation(((EventInfo)typeMember).GetAddMethod()))
          {
            return false;
          }
          method = ((EventInfo)typeMember).GetRemoveMethod();
          break;
        case MemberTypes.Property:
          method = ((PropertyInfo)typeMember).GetGetMethod();
        default:
          method = (MethodInfo)typeMember;
          break;
        }
        if (!IsAbstractImplementation(method))
        {
          return false;
        }
      }
    }
    return true;
  }

  public static bool IsAbstractImplementation(MethodInfo methodInfo)
  {
    const MethodAttributes expectedAttributes =
      MethodAttributes.Abstract |
      MethodAttributes.Public |
      MethodAttributes.NewSlot |
      MethodAttributes.Virtual;

    return (methodInfo.Attributes & expectedAttributes) == expectedAttributes;
  }

Without compiling it I already see a problem with properties, that the code has to check whether interface defines getter and/or setter and verify the right method(s), instead of blindly assuming the getter. Anyway, as one can see, the code is pretty dull. I am wondering if there is a better way...

EDIT 2

  • I wish to stress, that this is just a draft implementation, it works for simple cases and it is broken for more complex ones, like when there are method overloads or method renames (I do not know VB, so I did not even think it was possible). But it emphasizes my point that it demands much work to do it right.
  • Why would I want such a thing? We need to create types dynamically using Reflection.Emit based on certain dynamically acquired metadata. The generated dynamic type implements certain interface, say IDynamicObject, and may derive from some ancestor type. That ancestor type is statically compiled. Until recently, the ancestor type was not allowed to implement the IDynamicObject interface. Given an instance of the dynamic type, one had to explicitly cast it to IDynamicObject in order to gain access to its methods (remember, that the generated dynamic type does implement the interface). I would like to eliminate these explicit casts. The only way to do so is by letting the ancestor type implement the IDynamicObject interface. However, the implementation must be all abstract, which is verified by the dynamic type creation code. Voila.
like image 848
mark Avatar asked Oct 28 '09 19:10

mark


1 Answers

You can determine if a type implements a particular interface by using Type.IsAssignableFrom:

typeof(MyInterface).IsAssignableFrom(abstractType);

Edit: after clarification was added to the answer - to determine if all of an interface's implementations are abstract for a given class, you can do so much more easily by getting an InterfaceMap for the type in question:

bool IsAbstractOfInterface(Type classType, Type interfaceType)
{
    var map = classType.GetInterfaceMap(interfaceType);
    foreach (var info in map.TargetMethods)
    {
        if (!info.IsAbstract)
        {
            return false;
        }
    }
    return true;
}

Or maybe a generic extension method...

public static bool IsAbstractOf<TInterface>(this Type type)
{
    var map = type.GetInterfaceMap(typeof(TInterface));
    foreach (var info in map.TargetMethods)
    {
        if (!info.IsAbstract)
        {
            return false;
        }
    }
    return true;
}
like image 169
Rex M Avatar answered Nov 20 '22 06:11

Rex M