Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# BindingFlags.DeclaredOnly可避免派生类属性不明确的替代方法(AmbiguousMatchException)_C#_.net_Reflection - Fatal编程技术网

C# BindingFlags.DeclaredOnly可避免派生类属性不明确的替代方法(AmbiguousMatchException)

C# BindingFlags.DeclaredOnly可避免派生类属性不明确的替代方法(AmbiguousMatchException),c#,.net,reflection,C#,.net,Reflection,我正在寻找一种解决方案,通过属性名称的反射来访问类及其派生的“扁平”(最低)属性值 ie从ClassB或ClassC类型访问Property1或Property2: 使用简单反射可以一直工作,直到您拥有过度使用的虚拟属性(即ClassB中的Property1)。然后您会得到一个含糊不清的UsMatchException,因为搜索者不知道您想要的是主类的属性还是派生类的属性 使用BindingFlags.Declared只能避免含糊不清的UsMatchException,但未覆盖的虚拟属性或派生类

我正在寻找一种解决方案,通过属性名称的反射来访问类及其派生的“扁平”(最低)属性值

ie从ClassB或ClassC类型访问Property1或Property2:

使用简单反射可以一直工作,直到您拥有过度使用的虚拟属性(即ClassB中的Property1)。然后您会得到一个含糊不清的UsMatchException,因为搜索者不知道您想要的是主类的属性还是派生类的属性

使用BindingFlags.Declared只能避免含糊不清的UsMatchException,但未覆盖的虚拟属性或派生类属性会被忽略(即ClassB中的Property2)

除了这一糟糕的解决办法,还有其他办法吗

// Get the main class property with the specified propertyName
PropertyInfo propertyInfo = _type.GetProperty(propertyName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    // If not found, get the property wherever it is
    if (propertyInfo == null)
            propertyInfo = _type.GetProperty(propertyName);
此外,此解决方案无法解决第二级属性的反射:从ClassC获取Property1,而含糊不清的MatchException又回来了

我的想法:除了循环,我别无选择。。。呃

我对Emit、Lambda(是表达式.Call可以处理这个问题吗?)甚至DLR解决方案都持开放态度


谢谢

唯一的方法是枚举所有属性并过滤掉重复的属性

我建议你使用一个像这样的图书馆。它解决了困难的问题,并为您提供了比标准反射更好的特性

// find properties and remove duplicates higher up the hierarchy
var properties = type.Properties( Flags.ExcludeBackingMembers );

使用Fasterflect的解决方案:

foreach (PropertyInfo propertyInfo in objType.Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Static | Flags.Instance))
{
    FasterflectPropertyValue(propertyInfo.Name, obj);
}

private static object FasterflectPropertyValue(string propertyName, object obj)
{
    return obj.GetPropertyValue(propertyName);
}
来自Class1-1循环的反射:3602674ticks

来自Class2-1循环的反射:2940541滴答声

来自Class3-1循环的反射:1035300ticks

来自Class1-100循环的反射:2ms

来自Class2-100循环的反射:2ms

来自Class3-100循环的反射:3ms

来自Class1-10000循环的反射:274ms

来自Class2-10000循环的反射:284ms

来自Class3-10000循环的反射:295ms

从Class1-1循环中快速选择:44ms

Fasterflect from Class2-1循环:2508656ticks

Fasterflect from Class3-1循环:2314142滴答声

Fasterflect from Class1-100循环:3223064次

Fasterflect from Class2-100循环:5056514个滴答声

Fasterflect from Class3-100循环:5166725ticks

从Class1-10000循环中快速选择:96ms

从Class2-10000循环中快速选择:138ms


Fasterflect from Class3-10000 loops:162ms

+1用于Fasterflect,但我想它的效率不如emit/expression tree/DLR代码?它使用emit-under-of-cover,但不用于查找(因为这不是一个选项)。
foreach (PropertyInfo propertyInfo in objType.Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Static | Flags.Instance))
{
    FasterflectPropertyValue(propertyInfo.Name, obj);
}

private static object FasterflectPropertyValue(string propertyName, object obj)
{
    return obj.GetPropertyValue(propertyName);
}