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

C# 如何使用反射来获取显式实现接口的属性?,c#,reflection,explicit-interface,C#,Reflection,Explicit Interface,更具体地说,如果我有: public class TempClass : TempInterface { int TempInterface.TempProperty { get; set; } int TempInterface.TempProperty2 { get; set; } public int TempProperty { get;

更具体地说,如果我有:

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的属性获取所有PropertyInfo


谢谢。

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


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

Jacob的代码缺少过滤器:

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

显式实现的接口属性的属性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);
      }
    }
  }

以下是基于中给出的实现的改进解决方案:


我不得不修改雅各布·卡彭特的答案,但效果很好。nobugz也可以,但Jacobs更紧凑

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

我想你要找的课程是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));
}
Type ifaceType=typeof(临时接口);
Type TENTYPE=typeof(TempClass);
InterfaceMapping map=testype.GetInterfaceMap(ifaceType);
for(int i=0;i
建筑在:


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

我的解决方案是针对这样一种情况,即您知道要查找的属性的名称,并且非常简单

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

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

一个简单的帮助器类,可以帮助:

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]; }
    }
}
公共类接口属性映射
{
私有只读字典映射;
公共接口属性映射(类型)
{
this.Interfaces=type.GetInterfaces();
var properties=type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
this.map=新字典(this.Interfaces.Length);
foreach(此.Interfaces中的var intr)
{
var interfaceMap=type.GetInterfaceMap(intr);
Add(intr,properties.Where(p=>interfaceMap.TargetMethods
.Any(t=>t==p.getMethod(true)||
t==p.GetSetMethod(true)))
.Distinct().ToArray());
}
}
公共类型[]接口{get;private set;}
公共属性信息[]此[Type interfaceType]
{
获取{返回this.map[interfaceType];}
}
}

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

如果一个类实现了一个接口,它将实现该接口中的所有属性和方法。因此,您不必检查类的成员,只需检查接口的成员。您必须将接口成员与类成员进行比较,以确定该成员是否显式实现。如果您只需要TempInterface的接口属性,为什么不从typeof(TempInterface)开始因为那需要我比我聪明。你能确切地说明你在找什么吗?您是否只需要TempClass显式实现的所有属性的列表?还是只需要TempInterface的属性?等等,我想要一个由tempclass显式实现的所有属性的列表。您知道假定getAccessor为isPrivate是否可以吗?这永远是真的吗?另外,两个get/set方法是否都被标记为final,或者一个方法可能是final而不是final。谢谢。对于显式实现的属性,这两种方法的可访问性是相同的。从类的约定的角度来看,这两个方法都是私有的。当枚举explicitProperties时,我得到一个空引用错误。我认为不能使用GetProperties。因此,两个get/set方法都将标记为final?有可能是一个而不是另一个吗?谢谢。请注意,在代码段中使用了“get_uu”和“set_u”。您的答案是get methods,Jacob's是按照您最初在问题中提出的方式获取属性。
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); }
    }
}
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]; }
    }
}