方法也是如此:
我得到了两个PropertyInfo实例或者从它们所在的类GetProperty()或者GetMember()等等中提取的方法(或者可能来自MemberExpression).
我想确定它们是否实际上指的是相同的属性或相同的方法
(propertyOne == propertyTwo)
Run Code Online (Sandbox Code Playgroud)
要么
(methodOne == methodTwo)
Run Code Online (Sandbox Code Playgroud)
显然,这不会真正起作用,您可能正在查看相同的属性,但它可能是从类层次结构的不同级别(通常在这种情况下propertyOne != propertyTwo)中提取的
当然,我可以查看DeclaringType,并重新请求该属性,但是当你开始考虑时,这开始变得有点混乱
在一天结束时,我只是想能够在两个属性或两个方法之间进行智能相等检查,我80%确定上述要点并未涵盖所有边缘情况,而我我可以坐下来,写一堆测试并开始玩,我很清楚我对这些概念实际实现方式的低级知识并不是很好,我希望这是一个已经回答的主题,我只是吮吸搜索.
最好的答案会给我一些实现上述目标的方法,解释已经处理了哪些边缘情况以及为什么:-)
澄清:
从字面上看,我想确保它们是同一个属性,这里有一些例子
public interface IFoo
{
string Bar { get; set; }
}
public class Foo : IFoo
{
string Bar { get; set; }
}
typeof(IFoo).GetProperty("Bar")
Run Code Online (Sandbox Code Playgroud)
和
typeof(Foo).GetProperty("Bar")
Run Code Online (Sandbox Code Playgroud)
将返回两个不相等的属性信息:
public class BaseClass
{
public string SomeProperty { get; set ; }
}
public class DerivedClass : BaseClass { }
typeof(BaseClass).GetMethod("SomeProperty")
Run Code Online (Sandbox Code Playgroud)
和
typeof(DerivedClass).GetProperty("SomeProperty")
Run Code Online (Sandbox Code Playgroud)
我实际上无法记住这两个现在是否会返回相同的对象,但在我的世界中它们是平等的.
同理:
public class BaseClass
{
public virtual SomeMethod() { }
}
public class DerivedClass
{
public override SomeMethod() { }
}
typeof(BaseClass).GetMethod("SomeMethod")
Run Code Online (Sandbox Code Playgroud)
和
typeof(DerivedClass).GetProperty("SomeMethod")
Run Code Online (Sandbox Code Playgroud)
再次,这些不匹配 - 但我希望它们(我知道它们不是特别相同,但在我的域中它们是因为它们引用相同的原始属性)
我可以在结构上做到这一点,但这将是"错误的".
进一步说明:
你怎么甚至要求隐藏另一处房产的房产呢?似乎我之前的一个假设是无效的,默认情况下默认实现GetProperty("name")将引用当前级别.
BindingFlags.DeclaringType 似乎只是为了最终返回null!
查看PropertyInfo您IFoo/Foo示例中的对象,我们可以得出以下结论:
Type.GetInterfaces从那里调用和工作。不要忘记接口可以实现其他接口,因此这必须是递归的。那么让我们来尝试一下吧。首先,覆盖继承的属性:
PropertyInfo GetRootProperty(PropertyInfo pi)
{
var type = pi.DeclaringType;
while (true) {
type = type.BaseType;
if (type == null) {
return pi;
}
var flags = BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.Static;
var inheritedProperty = type.GetProperty(pi.Name, flags);
if (inheritedProperty == null) {
return pi;
}
pi = inheritedProperty;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,涵盖接口中声明的属性(使用 DFS 搜索):
PropertyInfo GetImplementedProperty(PropertyInfo pi)
{
var type = pi.DeclaringType;
var interfaces = type.GetInterfaces();
if (interfaces.Length == 0) {
return pi;
}
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public;
var query = from iface in interfaces
let implementedProperty = iface.GetProperty(pi.Name, flags)
where implementedProperty != pi
select implementedProperty;
return query.DefaultIfEmpty(pi).First();
}
Run Code Online (Sandbox Code Playgroud)
将这些结合在一起:
PropertyInfo GetSourceProperty(PropertyInfo pi)
{
var inherited = this.GetRootProperty(pi);
if (inherited != pi) {
return inherited;
}
var implemented = this.GetImplementedProperty(pi);
if (implemented != pi) {
return implemented;
}
return pi;
}
Run Code Online (Sandbox Code Playgroud)
这应该有效。它没有考虑具有相同名称但不同类型和/或数量的索引参数的索引属性,因此这留给读者作为众所周知的练习。
免责声明:我什至没有编译这个(现在没有时间运行测试)。它旨在作为“the”答案的起点,因为到目前为止还没有答案。
| 归档时间: |
|
| 查看次数: |
1306 次 |
| 最近记录: |