c# - 获取对象实例上自定义属性的*值*?

标签 c# reflection customtypedescriptor runtime-type

使用 .NET 4,C#

假设我有一个类 Info延伸 CustomTypeDescriptor .类的实例 Info有字典 <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) ,但按照我的理解,它希望我返回另一个具有匹配的真实(编译)属性的 type 的实例。

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

这可能吗?

最佳答案

您需要自己实现 PropertyDescriptor类重写 GetValue方法。所以而不是 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);
        }
    }
}

关于c# - 获取对象实例上自定义属性的*值*?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7889721/

相关文章:

java - 带有注解的 GSON 自定义序列化

c# - ICustomTypeDescriptor、TypeDescriptionProvider、TypeConverter 和 UITypeEditor

c# - 检测在 C# 中使用 openas_rundll 打开的选定程序

c# - C 类 : A : B 时访问同名成员

c# - 使用内部构造函数实例化类

c# - 反射 - 从 System.Type 实例获取通用参数

c# - 如何避免为我的每个类使用单独的自定义 TypeDescriptor Provider?

c# - Assembly.GetTypes() - 获取加载失败的类型

c# - C 与 C# 或 JAVA 中的 char 有什么区别