C#获取对象';s实际的TypeDescriptionProvider或TypeDescriptor
我意识到这是一个不寻常的问题,但: 我已经创建了一个自定义TypeDescriptionProvider,它可以根据请求的对象类型存储和返回不同的C#获取对象';s实际的TypeDescriptionProvider或TypeDescriptor,c#,C#,我意识到这是一个不寻常的问题,但: 我已经创建了一个自定义TypeDescriptionProvider,它可以根据请求的对象类型存储和返回不同的类型描述符。然而,我注意到,无论与类型(无论是自定义的还是默认的)关联的TypeDescriptionProvider,TypeDescriptor.GetProvider()始终返回(内部类)System.ComponentModel.TypeDescriptionNode对象(围绕实际的TypeDescriptionProvider)的某种包装。反
类型描述符。然而,我注意到,无论与类型(无论是自定义的还是默认的)关联的TypeDescriptionProvider
,TypeDescriptor.GetProvider()
始终返回(内部类)System.ComponentModel.TypeDescriptionNode
对象(围绕实际的TypeDescriptionProvider
)的某种包装。反过来,在此对象上调用GetTypeDescriptor()
总是返回一个System.ComponentModel.TypeDescriptor.TypeDescriptionNode.DefaultTypeDescriptor
对象(另一个包装)陌生人仍然不调用TypeDescriptionProvider
的实际GetTypeDescriptor()
方法
这是否意味着真的没有办法从对象的提供者那里获取对象的实际TypeDescriptionProvider
或其TypeDescriptor
?返回类名、属性等的方法在DefaultTypeDescriptor
上仍按预期工作,但我无法比较或找出两个对象是否相同使用相同的TypeDescriptor
(这是我当前需要的)
有人知道如何获取实际的TypeDescriptionProvider
,或者从包装的提供程序获取实际的TypeDescriptor吗
先谢谢你
例:
公共类TestTypeDescriptionProvider:TypeDescriptionProvider
{
私有静态字典_描述符=新字典();
…要添加到缓存的静态方法。。。
公共重写ICustomTypeDescriptor GetTypeDescriptor(类型objectType,对象实例)
{
if(objectType==null)
返回_描述符[instance.GetType()];
返回_描述符[objectType];
}
}
...
TypeDescriptionProvider p=TypeDescriptor.GetProvider(obj.GetType());//p是TypeDescriptionNode
ICustomTypeDescriptor td=p.GetTypeDescriptor(obj);//td是一个DefaultTypeDescriptor
您可以检查这两种类型是否具有相同的TypeDescriptionProviderAttribute
如果查看TypeDescriptor.GetProvider
实现,使用.NET Reflector等工具,您将看到返回的类型是相当硬编码的。它总是返回一个TypeDescriptionNode
,正如您所观察到的。相同的用于GetTypeDescriptor
的目录
现在,您可以使用反射机制从TypeDescriptionNode
获取实际的TypeDescriptionProvider
。这很简单,只需获取名为Provider
的私有字段,这是TypeDescriptionNode存储实际实现的地方。当然它不受支持,但我不认为这是我将在不久的将来进行更改,我真的看不到更好的方法…谢谢您的回答,但我需要比较的是提供程序将返回的ICustomTypeDescriptor。我还希望它足够通用,即使TypeDescriptionProvider是从没有属性的代码附加的,它也能工作。我同意我可以编写一个比较器,可以查看每个ICustomTypeDescriptor的各个属性,但是这会非常慢。类名本身不能保证是唯一的…应该有一种方法来进行引用比较。据我所知,除了反映私有成员之外,没有其他方法可以直接访问底层提供程序。谢谢感谢您的评论和对我的问题的调查。MS将这些限制放在适当的位置似乎很奇怪。感谢您的回复。我正在考虑这个选项,但假设应该有一个“受支持”的方法来实现这一点。因为TypeDescriptor系统允许在运行时添加TypeDescriptor,以每种类型或每种类型为单位基于每个对象,这似乎是一个应该经常出现的要求-尤其是对于PropertyGrid控件等@ach-您无法确定幕后实际工作的TypeDescriptor,但行为是预期的。最终,系统的DefaultTypeDescriptor会调用配置的TypeDescriptor。PropertyGrids其他动态控件只是得到一个ICustomTypeDescriptor,它们不关心实际的实现类型,它们只关心ICustomTypeDescriptor定义的行为和契约。我确实理解,在大多数情况下,您描述的行为是最终目标;但是,如果我创建的PropertyGrid可以显示多个对象和类型同时出现(如winforms中),我不想单独比较每个对象的propertyDescriptor集,而是比较TypeDescriptor。如果我有200个未知对象的集合,一些TypeA、一些TypeB和一些带有自定义TypeDescriptor的TypeA,以查找公共属性(不比较类型描述符)我必须比较每个对象的PropertyDescriptor,这是一项慢一个数量级、强度更高的任务。@ach-好的,但事实上,在多个选定对象的情况下,Winforms PropertyGrid(例如Winforms PropertyGrid)不是这样工作的,它只是从所有类型描述符中构建一个包含所有属性的哈希表/字典(无论它们是自定义的还是非自定义的),并显示它们。我真的不认为需要“比较”属性描述符。
public class TestTypeDescriptionProvider : TypeDescriptionProvider
{
private static Dictionary<Type, ICustomTypeDescriptor> _descriptors = new Dictionary<Type, ICustomTypeDescriptor>();
...static method to add to the cache...
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
if (objectType == null)
return _descriptors[instance.GetType()];
return _descriptors[objectType];
}
}
...
TypeDescriptionProvider p = TypeDescriptor.GetProvider(obj.GetType()); //p is a TypeDescriptionNode
ICustomTypeDescriptor td = p.GetTypeDescriptor(obj); // td is a DefaultTypeDescriptor