簡體   English   中英

獲取對象實例上的自定義屬性的* value *?

[英]Get *value* of custom property on object instance?

使用.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) ,但是我理解它的方式,它希望我返回另一個具有匹配實數(已編譯)的類型的實例屬性。

我希望能夠自己編寫屬性的實際實現(對於此示例,返回其鍵與屬性名稱匹配的字典中的值)。

這可能嗎?

您需要自己實現PropertyDescriptor類重寫GetValue方法。 因此,您將使用新的MyCoolPropertyDescriptor(dictionary, kvp.Key)等來代替TypeDescriptor.CreateProperty

以下是如何實施的示例:


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來獲得我認為你想要的那種功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM