Get runtime getter of interface property

Declarations:

interface I
{
    int i { get; set; }
}

class C : I
{
    public int i { get; set; }
}

Code:

C c = new C();
c.i = 10;
PropertyInfo pi1 =
    c.
    GetType().
    GetInterfaces().
    SelectMany(t => t.GetProperties()).
    ToArray()[0];
PropertyInfo pi2 =
    c.
    GetType().
    GetProperties()[0];
object v1 = pi1.GetValue(c);
object v2 = pi2.GetValue(c);

Hey, v1 == v2, pi1 != pi2, but GetValue obviously calls same method. How can I know in my code that pi1 and pi2 call same method body?

Jon Skeet
people
quotationmark

You can use Type.GetInterfaceMap() to get a mapping between interface members and the implementing members for a specific type. Here's an example:

using System;
using System.Linq;
using System.Threading;

interface I
{
    int Value { get; set; }
}

class C : I
{
    public int Value { get; set; }
}

public class Test
{
    static void Main()
    {
        var interfaceGetter = typeof(I).GetProperty("Value").GetMethod;
        var classGetter = typeof(C).GetProperty("Value").GetMethod;
        var interfaceMapping = typeof(C).GetInterfaceMap(typeof(I));

        var interfaceMethods = interfaceMapping.InterfaceMethods;
        var targetMethods = interfaceMapping.TargetMethods;
        for (int i = 0; i < interfaceMethods.Length; i++)
        {
            if (interfaceMethods[i] == interfaceGetter)
            {
                var targetMethod = targetMethods[i];
                Console.WriteLine($"Implementation is classGetter? {targetMethod == classGetter}");
            }
        }
    }
}

That prints Implementation is classGetter? True - but if you change the code so that fetching I.Value doesn't call C.Value, e.g. by adding a base class so that C.Value is a new property, not an implementation of I.Value:

interface I
{
    int Value { get; set; }
}

class Foo : I
{
    public int Value { get; set; }
}

class C : Foo
{
    public int Value { get; set; }
}

... then it will print Implementation is classGetter? False.

people

See more on this question at Stackoverflow