[英]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屬性,那么你需要查看DynamicObject
或ExpandoObject
來獲得我認為你想要的那種功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.