Karl Cassar Karl Cassar - 27 days ago 9
C# Question

How to know if a MemberInfo is an explicit implementation of a property

Imagine I have the code below. How can I get by reflection the

MemberInfo/PropertyInfo
for the 'explicit' implementation of
Test.Name
?

Also, is there any way to programmatically know that a
MemberInfo
is an explicit implementation of an interface property?

public interface ITest
{
string Title { get; set; }
}

public interface IExplicit
{
string Name { get; set; }
}

public class Test : ITest,IExplicit
{

public string Title { get; set; }

string IExplict.Name
{
get
{
return this.Title;

}
set
{

}
}
}

Answer

Imagine you have this interface:

interface ITest
{
    bool MyProperty { get; set; }
}

Implemented in this class:

class Test : ITest
{
    bool ITest.MyProperty { get; set; }
}

Now let's add this property to Test (note they have the same name):

public bool MyProperty { get; set; }

With a plain GetProperties() you won't get the explicit interface implementation (because it's always a private member):

int count = new Test().GetType().GetProperties().Length; // It's 1!

If you include both Public and NonPublic members you'll get both. To distinguish them you can rely first on name: the explicit implementation will contain the full interface name (so you can look for a ., it won't be there for a normal property because it's not an allowed char):

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    return property.Name.Contains(".");
}

It's a little bit naive so you may want some extra check, you can assert that get method of that property will:

  • Is virtual and sealed.
  • Is private.
  • Contains at least one dot.
  • Won't start with get_ or _set

Let's change code:

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    // This check is not mandatory and not cross-languages.
    // How this method is named may vary
    if (!property.Name.Contains("."))
        return false;

    if (property.Name.StartsWith("get_"))
        return false;

    if (!property.GetMethod.IsFinal)
        return false;

    if (!property.GetMethod.IsVirtual)
        return false;

    if (!property.GetMethod.IsPrivate)
        return false;

    return true;
}

Of course not all these checks are needed, I think first two are enough to exclude most of compiler generated code.

If you know which interface may be explicitly implemented you'll find this question here on SO pretty useful: How to find if a method is implementing specific interface

EDIT
From comments I thought about this and I found there is not a proper way to do it, CLR does not apply any rule (AFAIK) because what's needed is just the link between interface method and class method (no matters how it's called). I suppose (but it may be relaxed or expanded for other languages, if someone would contribute with more tests I'll make this answer a wiki) this code may work in most cases (thanks Alxandr for the hint):

First generic function to check if a method (given a MethodInfo) is an explicit interface implementation or not.

What we can't assert:

  • We can't use name (to check, for example ".") because it's implementation dependent (C# uses interfaceName.methodName but other languages do not).

  • We can't rely on check for private because (for example) in C++/CLI it can be a public method (with another name) moreover an interface can be "hacked" to be internal but the implementer to be public (so method won't be public too).

What we may assert:

  • An explicit interface implementation is always sealed and virtual. Maybe its' not true for all languages so we may relax this rule.

  • If a method has not the same name of the method declared in the interface it implements then it's an explicit implementation.

This is the code:

public static bool IsExplicitInterfaceImplementation(MethodInfo method)
{
    // Check all interfaces implemented in the type that declares
    // the method we want to check, with this we'll exclude all methods
    // that don't implement an interface method
    var declaringType = method.DeclaringType;
    foreach (var implementedInterface in declaringType.GetInterfaces())
    {
        var mapping = declaringType.GetInterfaceMap(implementedInterface);

        // If interface isn't implemented in the type that owns
        // this method then we can ignore it (for sure it's not
        // an explicit implementation)
        if (mapping.TargetType != declaringType)
            continue;

        // Is this method the implementation of this interface?
        int methodIndex = Array.IndexOf(mapping.TargetMethods, method);
        if (methodIndex == -1)
            continue;

        // Is it true for any language? Can we just skip this check?
        if (!method.IsFinal || !method.IsVirtual)
            return false;

        // It's not required in all languages to implement every method
        // in the interface (if the type is abstract)
        string methodName = "";
        if (mapping.InterfaceMethods[methodIndex] != null)
            methodName = mapping.InterfaceMethods[methodIndex].Name;

        // If names don't match then it's explicit
        if (!method.Name.Equals(interfaceMethodName, StringComparison.Ordinal))
            return true;
    }

    return false;
}

With this auxiliary function to do the check for properties:

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    // At least one accessor must exists, I arbitrary check first for
    // "get" one. Note that in Managed C++ (not C++ CLI) these methods
    // are logically separated so they may follow different rules (one of them
    // is explicit and the other one is not). It's a pretty corner case
    // so we may just ignore it.
    if (property.GetMethod != null)
        return IsExplicitInterfaceImplementation(property.GetMethod);

    return IsExplicitInterfaceImplementation(property.SetMethod);
}
Comments