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