gpt4 book ai didi

c# - 这是.Net 反射中的错误吗?

转载 作者:太空狗 更新时间:2023-10-29 22:33:21 24 4
gpt4 key购买 nike

答案是: 不,这不是错误。区别在于 ReflectedType .

所以这里真正的问题是:有没有一种方法可以比较两个 PropertyInfo 对象,对于相同的属性,但是从不同的类型反射(reflect)出来,以便它返回

原始问题

此代码通过使用两种不同的方式,为完全相同的属性 生成两个PropertyInfo 对象。结果,这些属性信息以某种方式比较不同。我花了一些时间试图弄清楚这一点。

我做错了什么?

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace TestReflectionError
{
class Program
{
static void Main(string[] args)
{
Console.BufferWidth = 200;
Console.WindowWidth = 200;

Expression<Func<object>> expr = () => ((ClassA)null).ValueA;
PropertyInfo pi1 = (((expr as LambdaExpression)
.Body as UnaryExpression)
.Operand as MemberExpression)
.Member as PropertyInfo;

PropertyInfo pi2 = typeof(ClassB).GetProperties()
.Where(x => x.Name == "ValueA").Single();

Console.WriteLine("{0}, {1}, {2}, {3}, {4}", pi1, pi1.DeclaringType, pi1.MemberType, pi1.MetadataToken, pi1.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}", pi2, pi2.DeclaringType, pi2.MemberType, pi2.MetadataToken, pi2.Module);

// these two comparisons FAIL
Console.WriteLine("pi1 == pi2: {0}", pi1 == pi2);
Console.WriteLine("pi1.Equals(pi2): {0}", pi1.Equals(pi2));

// this comparison passes
Console.WriteLine("pi1.DeclaringType == pi2.DeclaringType: {0}", pi1.DeclaringType == pi2.DeclaringType);
Console.ReadKey();
}
}

class ClassA
{
public int ValueA { get; set; }
}

class ClassB : ClassA
{
}
}

这里的输出是:

Int32 ValueA, TestReflectionError.ClassA, Property, 385875969, TestReflectionError.exe
Int32 ValueA, TestReflectionError.ClassA, Property, 385875969, TestReflectionError.exe
pi1 == pi2: False
pi1.Equals(pi2): False
pi1.DeclaringType == pi2.DeclaringType: True


罪魁祸首:PropertyInfo.ReflectedType

我发现这两个对象之间存在差异......它在 ReflectedType 中。文档是这样说的:

Gets the class object that was used to obtain this member.

最佳答案

你为什么不直接比较 MetadataToken 和 Module.

根据该组合唯一标识的文档。

MemberInfo.MetadataToken
一个值,与 Module 结合使用,唯一标识元数据元素。

static void Main(string[] args)
{
Console.BufferWidth = 200;
Console.WindowWidth = 140;

PropertyInfo pi1 = typeof(ClassA).GetProperties()
.Where(x => x.Name == "ValueA").Single();
PropertyInfo pi2 = typeof(ClassB).GetProperties()
.Where(x => x.Name == "ValueA").Single();
PropertyInfo pi0 = typeof(ClassA).GetProperties()
.Where(x => x.Name == "ValueB").Single();
PropertyInfo pi3 = typeof(ClassB).GetProperties()
.Where(x => x.Name == "ValueB").Single();
PropertyInfo pi4 = typeof(ClassC).GetProperties()
.Where(x => x.Name == "ValueA").Single();
PropertyInfo pi5 = typeof(ClassC).GetProperties()
.Where(x => x.Name == "ValueB").Single();


Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi1, pi1.ReflectedType, pi1.DeclaringType, pi1.MemberType, pi1.MetadataToken, pi1.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi2, pi2.ReflectedType, pi2.DeclaringType, pi2.MemberType, pi2.MetadataToken, pi2.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi0, pi0.ReflectedType, pi0.DeclaringType, pi0.MemberType, pi0.MetadataToken, pi1.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi3, pi3.ReflectedType, pi3.DeclaringType, pi3.MemberType, pi3.MetadataToken, pi3.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi4, pi4.ReflectedType, pi4.DeclaringType, pi4.MemberType, pi4.MetadataToken, pi4.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi5, pi5.ReflectedType, pi5.DeclaringType, pi5.MemberType, pi5.MetadataToken, pi5.Module);

// these two comparisons FAIL
Console.WriteLine("pi1 == pi2: {0}", pi1 == pi2);
Console.WriteLine("pi1.Equals(pi2): {0}", pi1.Equals(pi2));

// this comparison passes
Console.WriteLine("pi1.DeclaringType == pi2.DeclaringType: {0}", pi1.DeclaringType == pi2.DeclaringType);


pi1 = typeof(ClassA).GetProperties()
.Where(x => x.Name == "ValueB").Single();

pi2 = typeof(ClassB).GetProperties()
.Where(x => x.Name == "ValueB").Single();

Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi1, pi1.ReflectedType, pi1.DeclaringType, pi1.MemberType, pi1.MetadataToken, pi1.Module);
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", pi2, pi2.ReflectedType, pi2.DeclaringType, pi2.MemberType, pi2.MetadataToken, pi2.Module);

// these two comparisons FAIL
Console.WriteLine("pi1 == pi2: {0}", pi1 == pi2);
Console.WriteLine("pi1.Equals(pi2): {0}", pi1.Equals(pi2));


Console.ReadKey();
}
class ClassA
{
public int ValueA { get; set; }
public int ValueB { get; set; }
}
class ClassB : ClassA
{
public new int ValueB { get; set; }
}
class ClassC
{
public int ValueA { get; set; }
public int ValueB { get; set; }
}

关于c# - 这是.Net 反射中的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12765804/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com