简体   繁体   English

如何使用反射来获取显式实现接口的属性?

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

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? 如何使用反射来获取显式实现TempInterface的属性的所有propertyInfos?

Thanks. 谢谢。

I think the class you are looking for is System.Reflection.InterfaceMapping. 我认为您正在寻找的类是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));
}

The property getter and setter of an explicitly implemented interface property has an unusual attribute. 显式实现的接口属性的属性getter和setter具有不寻常的属性。 It's IsFinal property is True, even when it is not a member of a sealed class. 它的IsFinal属性是True,即使它不是密封类的成员。 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);
      }
    }
  }

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

Building on the answer by MrKurt : 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;

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. 您必须反映Interface类型的方法/属性,看它们是否存在于您的类类型中,并比较它们以确定它们是否存在时是否“相同”。

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. 如果它在两者之间,但两者之间不同,则它是一个显式接口。

I had to modify Jacob Carpenter's answer but it works nicely. 我不得不修改雅各布卡彭特的答案,但效果很好。 nobugz's also works but Jacobs is more compact. nobugz也有效,但Jacobs更紧凑。

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

A simple helper class that could help: 一个简单的帮助类可以帮助:

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

You'll get properties for each interface, even explicitly implemented. 您将获得每个接口的属性,甚至是明确实现的。

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

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. GetProperties需要两个搜索标志来获取私有属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用反射,如何在接口实现另一个接口时找到接口正在实现的方法 - Using reflection, how do I find the method an interface is implementing when it's implementing another interface 如何使用反射来执行显式实现的 static 抽象方法 - How do I use reflection to execute an explicitly-implemented static abstract method 如何使用反射获取对象的属性? - How do I get the properties of an object using reflection? 如何使用反射获取通用接口的实现 - How to use reflection to get implementations of a generic interface 如何使用反射来查找实现特定接口的属性? - How can I use reflection to find the properties which implement a specific interface? 如何使用反射获取属性并在查询中使用它? - How do I use reflection to get a property and use it in a query? 如何正确使用显式实现的接口属性和wpf可见性? - How do I use an explicitly implemented interface property and wpf visiblity together properly? 如何使用反射获取嵌套属性 - How do I use reflection to get the nested property 如何使用反射来获取方法的字段? - How do I use Reflection to get the fields of a method? 使用反射来获取继承接口的类的属性 - using reflection to get properties of class inheriting an interface
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM