在运行时添加属性

时间:2011-05-29 06:08:15

标签: c# properties runtime

我有一个程序员可以用来动态添加新属性的类。为此,它实现了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设置为实例属性。我认为这是正确的方法吗?

1 个答案:

答案 0 :(得分:17)

您已经在创建这样的集合:

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

但您创建的集合只包含现有属性,而不是新属性。

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

这样的事情:

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

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

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

这样的事情:

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不仅描述您的属性,还使客户端能够实际获取和设置这些属性的值。这就是重点,不是吗!