How do I use reflection to get properties explicitly implementing an interface?

后端 未结 9 1017
[愿得一人]
[愿得一人] 2021-01-03 20:18

More specifically, if I have:

public class TempClass : TempInterface
{

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


        
相关标签:
9条回答
  • 2021-01-03 20:31

    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);
          }
        }
      }
    
    0 讨论(0)
  • 2021-01-03 20:31

    Building on the answer by MrKurt:

    var targetMethods =
        from iface in typeof(TempClass).GetInterfaces()
        from method in typeof(TempClass).GetInterfaceMap(iface).TargetMethods
        select method;
    
    var explicitProps =
        from prop in typeof(TempClass).GetProperties(BindingFlags.Instance |
                                                     BindingFlags.NonPublic)
        where targetMethods.Contains(prop.GetGetMethod(true)) ||
              targetMethods.Contains(prop.GetSetMethod(true))
        select prop;
    
    0 讨论(0)
  • 2021-01-03 20:40

    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);
    
    0 讨论(0)
  • 2021-01-03 20:41

    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.

    0 讨论(0)
  • 2021-01-03 20:42

    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;
    
    0 讨论(0)
  • 2021-01-03 20:43

    This seems a bit painful for no apparent reason!

    My solution is for the case where you know the name of the property you are looking for and is pretty simple.

    I have a class for making reflection a bit easier that I just had to add this case to:

    public class PropertyInfoWrapper
    {
        private readonly object _parent;
        private readonly PropertyInfo _property;
    
        public PropertyInfoWrapper(object parent, string propertyToChange)
        {
            var type = parent.GetType();
            var privateProperties= type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
    
            var property = type.GetProperty(propertyToChange) ??
                           privateProperties.FirstOrDefault(p => UnQualifiedNameFor(p) == propertyName);
    
            if (property == null)
                throw new Exception(string.Format("cant find property |{0}|", propertyToChange));
    
            _parent = parent;
            _property = property;
        }
    
        private static string UnQualifiedNameFor(PropertyInfo p)
        {
            return p.Name.Split('.').Last();
        }
    
        public object Value
        {
            get { return _property.GetValue(_parent, null); }
            set { _property.SetValue(_parent, value, null); }
        }
    }
    

    You cant just do == on name because explicitly implemented properties have fully qualified names.

    GetProperties needs both the search flags to get at private properties.

    0 讨论(0)
提交回复
热议问题