Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
        {

        }
    }
}
like image 357
Karl Cassar Avatar asked Jul 25 '13 09:07

Karl Cassar


People also ask

What is explicit implementation?

Explicit implementation is also used to resolve cases where two interfaces each declare different members of the same name such as a property and a method. To implement both interfaces, a class has to use explicit implementation either for the property P , or the method P , or both, to avoid a compiler error.

What is PropertyInfo?

The PropertyInfo class discovers the attributes of a property and provides access to property metadata. The PropertyInfo class is very similar to the FieldInfo class and also contains the ability to set the value of the property on an instance.


2 Answers

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(methodName, 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);
}
like image 101
Adriano Repetti Avatar answered Oct 01 '22 16:10

Adriano Repetti


Use BindingFlags.Instance | BindingFlags.NonPublic binding flags to get members which declared explicitly. Also you need to specify full name for explicit members, if you want to get them by name:

Type type = typeof(Test);
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
var property = type.GetProperty("Namespace.IExplicit.Name", flags);

You can use this fact to filter only explicitly implemented memebers:

var explicitMembers = type.GetMembers(flags).Where(m => m.Name.Contains("."));
like image 43
Sergey Berezovskiy Avatar answered Oct 01 '22 16:10

Sergey Berezovskiy