2011-05-29 81 views
13

我有一个程序员可以用来动态添加新属性的类。为此,它实现了ICustomTypeDescriptor以便能够覆盖GetProperties()方法。在运行时添加属性

public class DynamicProperty 
{ 
    public object Value { get; set; } 

    public Type Type { get; set; } 

    public string Name { get; set; } 

    public Collection<Attribute> Attributes { get; set; } 
} 

public class DynamicClass : ICustomTypeDescriptor 
{ 
    // Collection to code add dynamic properties 
    public KeyedCollection<string, DynamicProperty> Properties 
    { 
     get; 
     private set; 
    } 

    // ICustomTypeDescriptor implementation 
    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() 
    { 
     // Properties founded within instance 
     PropertyInfo[] instanceProps = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 

     // Fill property collection with founded properties 
     PropertyDescriptorCollection propsCollection = 
      new PropertyDescriptorCollection(instanceProps.Cast<PropertyDescriptor>().ToArray()); 

     // Fill property collection with dynamic properties (Properties) 
     foreach (var prop in Properties) 
     { 
      // HOW TO? 
     } 

     return propsCollection; 
    } 
} 

是否可以遍历属性列表中的每个属性添加到PropertyDescriptorCollection

基本上我希望程序员能够将DynamicProperty添加到将由GetProperties处理的集合中。喜欢的东西:

new DynamicClass() 
{ 
    Properties = { 
     new DynamicProperty() { 
      Name = "StringProp", 
      Type = System.String, 
      Value = "My string here" 
     }, 

     new DynamicProperty() { 
      Name = "IntProp", 
      Type = System.Int32, 
      Value = 10 
     } 
    } 
} 

现在那些Properties将设置好的,以实例的属性,只要GetProperties被调用。我是否认为这是正确的方式?

回答

17

您已经创建了一个集合是这样的:

PropertyDescriptorCollection propsCollection = 
      new PropertyDescriptorCollection(instanceProps.Cast<PropertyDescriptor>().ToArray()); 

但你只创建集合了现有的属性,不是你的新属性。

您需要提供从现有属性和新属性连接的单个数组。

事情是这样的:

instanceProps.Cast<PropertyDescriptor>().Concat(customProperties).ToArray() 

下一个问题是:你需要customProperties这是PropertyDescriptor的集合。不幸的是PropertyDescriptor是一个抽象类,所以你没有一个简单的方法来创建一个。

虽然我们可以解决这个问题,但是通过派生自PropertyDescriptor并实现所有抽象方法来定义您自己的CustomPropertyDescriptor类。

事情是这样的:

public class CustomPropertyDescriptor : PropertyDescriptor 
{ 
    private Type propertyType; 
    private Type componentType; 

    public CustomPropertyDescriptor(string propertyName, Type propertyType, Type componentType) 
     : base(propertyName, new Attribute[] { }) 
    { 
     this.propertyType = propertyType; 
     this.componentType = componentType; 
    } 

    public override bool CanResetValue(object component) { return true; } 
    public override Type ComponentType { get { return componentType; } } 
    public override object GetValue(object component) { return 0; /* your code here to get a value */; } 
    public override bool IsReadOnly { get { return false; } } 
    public override Type PropertyType { get { return propertyType; } } 
    public override void ResetValue(object component) { SetValue(component, null); } 
    public override void SetValue(object component, object value) { /* your code here to set a value */; } 
    public override bool ShouldSerializeValue(object component) { return true; } 
} 

我还没有填写的电话来获取和设置你的属性;这些调用取决于您如何在引擎盖下实现动态属性。

然后你需要创建一个数组CustomPropertyDescriptor填充与您的动态属性相适应的信息,并将其连接到最初描述的基本属性。

PropertyDescriptor不仅描述了您的属性,它还使客户端能够实际获取和设置这些属性的值。这就是整个问题,不是!

+0

'propertyType'是属性本身的类型吧?那么componentType呢?它是属性所在的对象的类型? – Joao 2011-05-29 07:32:54

+0

'propertyType'是动态属性的类型。如果你有一个名为'Count'的动态整数属性,它会是'typeof(int)'。 'componentType'是具有动态属性的类的类型,例如'typeof运算(MyDynamicPropertyClass)'。 – 2011-05-29 07:37:30

+0

还有一个问题。这样,如果以前通过'Properties'列表添加的属性是动态访问的(例如使用'var'),我可以确定使用'GetProperties()'来访问所述属性吗? – Joao 2011-05-29 07:40:31

相关问题