【问题标题】:How do I use reflection to get properties explicitly implementing an interface?如何使用反射来获取显式实现接口的属性?
【发布时间】:2010-09-21 16:41:33
【问题描述】:

更具体地说,如果我有:

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;
    }
}

如何使用反射来获取显式实现 TempInterface 的属性的所有 propertyInfos?

谢谢。

【问题讨论】:

  • 您能否准确说明您要查找的内容?您是否只需要 TempClass 显式实现的所有属性的列表?还是您只想要 TempInterface 的属性?等
  • 我想要一份由 TempClass 显式实现的所有属性的列表

标签: c# reflection explicit-interface


【解决方案1】:

它过于复杂。您必须反思接口类型的方法/属性,查看它们是否存在于您的类类型中,并比较它们以查看它们是否存在时是否“相同”。

如果接口中有某些东西但不是您正在测试的类型,则它是显式实现。如果两者都存在,但两者不同,则为显式接口。

【讨论】:

  • 如果一个类实现了一个接口,它会实现该接口中的所有属性和方法。所以你不必检查类的成员,你只需要检查接口的成员。
  • 您必须将接口成员与类成员进行比较,以了解该成员是否显式实现。
【解决方案2】:

Jacob 的代码缺少过滤器:

        var props = typeof(TempClass).GetInterfaces().Where(i => i.Name=="TempInterface").SelectMany(i => i.GetProperties());
        foreach (var prop in props)
            Console.WriteLine(prop);

【讨论】:

  • 如果你只想要TempInterfaces的接口属性,为什么不从typeof(TempInterface)开始呢?
  • 因为这需要我比我更聪明。
【解决方案3】:

显式实现的接口属性的属性 getter 和 setter 具有不寻常的属性。它的 IsFinal 属性为 True,即使它不是密封类的成员。试试这个代码来验证我的断言:

  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);
      }
    }
  }

【讨论】:

  • 那么get/set方法都会被标记为final?有没有可能一个存在而另一个不存在?谢谢。
  • 注意sn-p中“get_”和“set_”的使用
【解决方案4】:

这是一个基于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);

【讨论】:

  • 你知道假设 getAccessor 是私有的是否可以吗?这会永远是真的吗?此外,get/set 方法是否都被标记为最终方法,或者是否有可能是一个而不是另一个。谢谢。
  • 对于显式实现的属性,两种方法的可访问性是相同的。从类契约的角度来看,这些方法都是私有的。
  • 在枚举explicitProperties 时出现空引用错误。
  • 我认为 GetProperties 不能用。
【解决方案5】:

我不得不修改 Jacob Carpenter 的答案,但效果很好。 nobugz 也可以,但 Jacobs 更紧凑。

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

【讨论】:

  • 您的答案是获取方法,Jacob 正在获取您最初在问题中提出的属性。
【解决方案6】:

我认为您正在寻找的类是 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));
}

【讨论】:

    【解决方案7】:

    基于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;
    

    【讨论】:

      【解决方案8】:

      这似乎有点痛苦,没有明显的原因!

      我的解决方案适用于您知道要查找的属性的名称并且非常简单的情况。

      我有一个让反射更容易的类,我只需将这个案例添加到:

      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); }
          }
      }
      

      您不能只对 name 执行 ==,因为显式实现的属性具有完全限定的名称。

      GetProperties 需要两个搜索标志才能获取私有属性。

      【讨论】:

        【解决方案9】:

        一个可以提供帮助的简单助手类:

        public class InterfacesPropertiesMap
        {
            private readonly Dictionary<Type, PropertyInfo[]> map;
        
            public InterfacesPropertiesMap(Type type)
            {
                this.Interfaces = type.GetInterfaces();
                var properties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
        
                this.map = new Dictionary<Type, PropertyInfo[]>(this.Interfaces.Length);
        
                foreach (var intr in this.Interfaces)
                {
                    var interfaceMap = type.GetInterfaceMap(intr);
                    this.map.Add(intr, properties.Where(p => interfaceMap.TargetMethods
                                                            .Any(t => t == p.GetGetMethod(true) ||
                                                                      t == p.GetSetMethod(true)))
                                                 .Distinct().ToArray());
                }
            }
        
            public Type[] Interfaces { get; private set; }
        
            public PropertyInfo[] this[Type interfaceType]
            {
                get { return this.map[interfaceType]; }
            }
        }
        

        您将获得每个接口的属性,甚至是显式实现的。

        【讨论】:

          猜你喜欢
          • 2011-09-18
          • 1970-01-01
          • 2010-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多