Gerd K
Gerd K

Reputation: 1147

C# Reflection test if member is an interface implementation

Suppose I have the following interface and implementing class:

public interface IInterface
{
    string AMember { get; }
    string OtherMember { get; }
}

public class Class : IInterface
{

    public string OtherMember { get { return "other"; } }

    public string AMember { get { return "class"; }}

    string IInterface.AMember { get { return "explicit"; } }

}

Now I get the members via reflection and want to test if they are an interface implementation.

public class Program
{
    public static void Main()
    {
        var inst = new Class();
        var members = typeof(Class).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach(var member in members)
        {
            object val;
            try
            {
                val = member.GetValue(inst);
            }
            catch(MethodAccessException e)
            {
                val = "EXPLICIT";
            }

            Console.Out.WriteLine(string.Format("{0}: {1} is interface implementation? {2}", member.Name, val, false /*member.IsInterfaceImplementation*/));
        }
    }
}

How can I test if the member is the implementation of an interface?

Upvotes: 1

Views: 1111

Answers (2)

InvisiblePanda
InvisiblePanda

Reputation: 1609

In case you really just want to check whether a member of a certain class comes from any interface, you could do the following:

bool myMemberComesFromInterface = typeof(Class).GetInterfaces()
    .SelectMany(i => i.GetMember("MyMember")).Any();

There is an edge case though: explicit interface implementation; consider:

public interface IInterface
{
    int MyMember { get; }
}

public class Class : IInterface
{
    public string MyMember => "foo";
    int IInterface.MyMember => 2;
}

The above code would yield true in this case and I can't be sure if that's what you want in your use case. If you don't want this, I think you'd have to do comparisons of the members you found with the SelectMany(...) on a per-interface basis. Perhaps InterfaceMapping (see here) could be of use as well here.

Edit: Since it is now clarified that this case is of interest, I tried fiddling something that would work for your case:

var interfaces = typeof(Class).GetInterfaces()
    .ToDictionary(i => i.FullName, i => i.GetProperties().Select(p => p.Name).ToList());
var properties = typeof(Class).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance);

// explicitly implemented properties
foreach (var pi in properties.Where(pi => pi.Name.Contains(".")))
{
    Console.WriteLine($"Explicitly implemented property {pi.Name} found.");
    var parts = pi.Name.Split('.');
    string interfaceName = string.Join(".", parts.Take(parts.Length - 1));
    string propertyName = parts[parts.Length - 1];
    interfaces[interfaceName].Remove(propertyName);
}

// rest
foreach (var pi in properties.Where(pi => !pi.Name.Contains(".")))
{
    // instead of this, you could also use LINQ and SelectMany
    // on the Values to check for containment
    bool found = false;
    foreach (var interfaceName in interfaces.Keys)
    {
        if (interfaces[interfaceName].Contains(pi.Name))
        {
            found = true;
            Console.WriteLine($"Found property {pi.Name} in interface {interfaceName}.");
        }
    }

    if (!found)
    {
        Console.WriteLine($"Property {pi.Name} is self-defined.");
    }
}

For your example, this give me the following output:

Explicitly implemented property Fiddle.IInterface.AMember found. Found property OtherMember in interface Fiddle.IInterface. Property AMember is self-defined.

Upvotes: 3

Harish Mashetty
Harish Mashetty

Reputation: 433

You can use the following code:

var interfaceType = typeof(IInterface);
var interfaceVar = typeof(Class).GetInterface(interfaceType.Name);
var returnMethod = interfaceVar.GetMethods().FirstOrDefault(m 
         =>m.ReturnType.IsSubclassOf("MyMember") || m.ReturnType == "MyMember");
 if(returnMethod != null){
  // your member is implementation of interface
   }

Upvotes: 0

Related Questions