views:

1997

answers:

6

More specifically, if I have:

public class TempClass : TempInterface
{

    int TempInterface.TempProperty
    {
     get;
     set;
    }
    int TempInterface.TempProperty2
    {
     get;
     set;
    }

    public int TempProperty
    {
     get;
     set;
    }
}

public interface TempInterface
{
    int TempProperty
    {
        get;
        set;
    }
    int TempProperty2
    {
        get;
        set;
    }
}

How do I use reflection to get all the propertyInfos for properties explicitly implementing TempInterface?

Thanks.

A: 

It's overly complex. You have to reflect over the methods/properties of the Interface type, see if they exist in your class type, and compare them to see if they're the "same" when they do exist.

If something is in the interface but not the type you're testing, it's an explicit implementation. If it's in both, but different between the two, it's an explicit interface.

Here's a useful blog post with some code for doing the work: http://hyperthink.net/blog/reflecting-over-explicit-interface-implementations/

MrKurt
If a class implements an interface, it implements all properties and methods in that interface. So you don't have to examine the members of the class, you just have to examine the members of the interface.
Robert Rossney
You have to compare the interface members to the class members to find out if the member is *explicitly* implemented or not.
MrKurt
A: 

Jacob's code is missing a filter:

        var props = typeof(TempClass).GetInterfaces().Where(i => i.Name=="TempInterface").SelectMany(i => i.GetProperties());
        foreach (var prop in props)
            Console.WriteLine(prop);
Robert Rossney
If you only want the interface properties of TempInterfaces, why not start with typeof(TempInterface)?
Jacob Carpenter
Because that would require me to be smarter than I am.
Robert Rossney
+2  A: 

The property getter and setter of an explicitly implemented interface property has an unusual attribute. It's IsFinal property is True, even when it is not a member of a sealed class. Try this code to verify my assertion:

  foreach (AssemblyName name in Assembly.GetEntryAssembly().GetReferencedAssemblies()) {
    Assembly asm = Assembly.Load(name);
    foreach (Type t in asm.GetTypes()) {
      if (t.IsAbstract) continue;
      foreach (MethodInfo mi in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)) {
        int dot = mi.Name.LastIndexOf('.');
        string s = mi.Name.Substring(dot + 1);
        if (!s.StartsWith("get_") && !s.StartsWith("set_")) continue;
        if (mi.IsFinal)
          Console.WriteLine(mi.Name);
      }
    }
  }
Hans Passant
So both the get/set methods will be marked final? Is it possible for one to be and not the other? thanks.
TheDeeno
Note the use of "get_" and "set_" in the snippet
Hans Passant
A: 

Here's a modified solution based on the implementation given in this blog post:

var explicitProperties =
    from prop in typeof(TempClass).GetProperties(
        BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
    let getAccessor = prop.GetGetMethod(true)
    where getAccessor.IsFinal && getAccessor.IsPrivate
    select prop;

foreach (var p in explicitProperties)
    Console.WriteLine(p.Name);
Jacob Carpenter
Do you know if its ok to assume the getAccessor isPrivate? Will this always be true? Also, will both the get/set methods be marked final or is it possible for one to be and not the other. thanks.
TheDeeno
The accessibility of both methods will be the same for an explicitly implemented property. The methods will both be private, from the perspective of the class's contract.
Jacob Carpenter
when enumerating explicitProperties I get a null reference error.
TheDeeno
I think GetProperties can't be used.
TheDeeno
A: 

I had to modify Jacob Carpenter's answer but it works nicely. nobugz's also works but Jacobs is more compact.

var explicitProperties =
from method in typeof(TempClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
where method.IsFinal && method.IsPrivate
select method;
TheDeeno
+2  A: 

I think the class you are looking for is System.Reflection.InterfaceMapping.

Type ifaceType = typeof(TempInterface);
Type tempType = typeof(TempClass);
InterfaceMapping map = tempType.GetInterfaceMap(ifaceType);
for (int i = 0; i < map.InterfaceMethods.Length; i++)
{
    MethodInfo ifaceMethod = map.InterfaceMethods[i];
    MethodInfo targetMethod = map.TargetMethods[i];
    Debug.WriteLine(String.Format("{0} maps to {1}", ifaceMethod, targetMethod));
}