2011-10-25 41 views
3

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

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

這可能嗎?

回答

3

您需要自己執行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); 
     } 
    } 
} 
 
2

我的CustomTypeDescriptor的理解是,它允許綁定暴露額外的屬性,比如說,一個網格,實際上並不對存在類。這不是擴展CLR的東西,以便您的實際類暴露該屬性。

如果您想要實際的CLR屬性,那麼您需要查看DynamicObjectExpandoObject以獲得我認爲您所追求的功能。

+0

我認爲可以使用CustomTypeDescriptor獲取動態屬性(儘管我可能會對其進行擴展)。但是,對於'動態'建議+1。我需要學習如何使用它:) –