我在玩System.ComponentModel.TypeDescriptor
时发现了一些有趣的东西:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime DateOfBirth { get; set; }
public Enum Enum { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var person = new Person();
var typeDescriptionProvider = TypeDescriptor.AddAttributes(person, new DescriptionAttribute("Some description of this person"));
// Returns no attributes if person is a *struct* instance,
// but does return the DescriptionAttribute if person is a *class* instance
--> var descriptionAttributes = TypeDescriptor.GetAttributes(person).OfType<DescriptionAttribute>().ToList();
// Always returns the DescriptionAttribute
var descriptionAttributesUsingTdp = typeDescriptionProvider.GetTypeDescriptor(person).GetAttributes().OfType<DescriptionAttribute>().ToList();
Console.ReadLine();
}
}
当Person
的定义是一个类时,-->
的代码行找到并返回DescriptionAttribute
就好了。
当我将Person
更改为结构时,代码找不到DescriptionAttribute
。
这种差异背后的理由是什么?对于值类型缺少的引用类型,是否存在一些魔力?
我知道-->
下面的代码行返回属性,无论Person的实例是类还是结构。这是因为the TypeDescriptionProvider
returned by the AddAttributes()
method call was the one that performed the addition。
答案 0 :(得分:3)
当TypeDescriptor.GetAttributes(person)
是结构时,为什么没有Person
返回属性?
TypeDescriptor.AddAttributes
和TypeDescriptor.GetAttributes
使用引用相等来查找TypeDescriptor
内部缓存中的对象。如果Person
是一个类,则这两个方法调用中的person
参数引用相同的实例。但是,如果Person
是一个结构,那么person
参数将被独立地加载到不同的实例中,因此GetAttributes
无法找到原始的person
}。
如果person
仅被装箱一次,则代码按预期工作:
object person = new Person(); // `object` instead of `var`
为什么typeDescriptionProvider.GetTypeDescriptor(person).GetAttributes()
始终返回属性?
TypeDescriptionProvider.GetTypeDescriptor(Object)
文档不清楚(至少对我来说),但请注意,您显然可以将任何传递给typeDescriptionProvider.GetTypeDescriptor
- 例如{{1} (一个结构)或42
(一个类) - 并返回你的属性:
"Hello, World!"
基于此行为,我的猜测是var descriptionAttributesUsingTdp = typeDescriptionProvider.GetTypeDescriptor(42)
.GetAttributes().OfType<DescriptionAttribute>().ToList();
// descriptionAttributesUsingTdp.Count == 1
返回的typeDescriptionProvider
与TypeDescriptor.AddAttributes(person, ...)
无关。相反,它代表一个插件,可以将您的属性添加到任何对象,而person
是执行此操作的方法。