获取对象实例上自定义属性的值



使用。net 4, c#

假设我有一个类Info,它扩展了CustomTypeDescriptorInfo类的实例有一个<string, object>对的字典,在运行时加载。

我希望能够将字典键作为属性公开(以便Info的每个实例具有不同的属性)。属性的值应该是字典中相应的值。

我开始暴露属性:

    public override PropertyDescriptorCollection GetProperties()
    {
        var orig = base.GetProperties();
        var newProps = dictionary.Select( kvp => 
                       TypeDescriptor.CreateProperty(
                           this.GetType(), 
                           kvp.key, 
                           typeof(string)));
        return new PropertyDescriptorCollection(
                   orig.Cast<PropertyDescriptor>()
                   .Concat(newProps)
                   .ToArray());
    }

问题是,我如何得到它们的值?

var info = new Info(new Dictionary<string, object>{{"some_property", 5}};
var prop = TypeDescriptor.GetProperties(i_info)["some_property"];
var val = prop.GetValue(i_info); //should return 5

prop.GetValue()被调用时,我发现获得控制的唯一方法是覆盖GetPropertyOwner(PropertyDescriptor pd),但我理解它的方式是,它希望我返回另一个类型的实例,该实例具有匹配的真实(编译)属性。

我希望能够自己编写属性的实际实现(在本例中,返回字典中键与属性名称匹配的值)。

这可能吗?

您需要自己实现覆盖GetValue方法的PropertyDescriptor类。所以代替TypeDescriptor.CreateProperty,你将使用新的MyCoolPropertyDescriptor(dictionary, kvp.Key)或类似的。

下面是如何实现它的示例:

<>之前 using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace ConsoleApplication1 { internal sealed class MyCoolPropertyDescriptor : PropertyDescriptor { private Func<object, object> propertyGetter; private Action<object, object> propertySetter; public MyCoolPropertyDescriptor( string name, Func<object, object> propertyGetter, Action<object, object> propertySetter) : base(name, new Attribute[] {}) { this.propertyGetter = propertyGetter; this.propertySetter = propertySetter; } public override bool CanResetValue(object component) { return true; } public override System.Type ComponentType { get { return typeof(object); } } public override object GetValue(object component) { return this.propertyGetter(component); } public override bool IsReadOnly { get { return false; } } public override System.Type PropertyType { get { return typeof(object); } } public override void ResetValue(object component) { this.propertySetter(component, null); } public override void SetValue(object component, object value) { this.propertySetter(component, value); } public override bool ShouldSerializeValue(object component) { return false; } } public sealed class Info : CustomTypeDescriptor { IDictionary<string, object> properties; public Info(IDictionary<string, object> properties) { this.properties = properties; } public override PropertyDescriptorCollection GetProperties() { var orig = base.GetProperties(); var newProps = this.properties .Select(kvp => new MyCoolPropertyDescriptor( kvp.Key, o => ((Info)o).properties[kvp.Key], (o, v) => ((Info)o).properties[kvp.Key] = v)); return new PropertyDescriptorCollection(orig .Cast<PropertyDescriptor>() .Concat(newProps) .ToArray()); } } internal class Program { private static void Main(string[] args) { var info = new Info(new Dictionary<string, object>{{"some_property", 5}}); var prop = TypeDescriptor.GetProperties(info)["some_property"]; var val = prop.GetValue(info); //should return 5 Console.WriteLine(val); } } }

我对CustomTypeDescriptor的理解是,它允许数据绑定将额外的属性暴露给,比如说,一个网格,而这些属性实际上并不存在于类中。它不是扩展CLR的东西,所以你的实际类公开属性。

如果你想要实际的CLR属性,那么你需要查看DynamicObjectExpandoObject来获得我认为你想要的那种功能。

相关内容

  • 没有找到相关文章

最新更新