C# 在运行时添加属性

C# 在运行时添加属性,c#,properties,runtime,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<Attrib

我有一个类,程序员可以使用它动态添加新属性。为此,它实现了
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;
    }
}

现在,只要调用
GetProperties
,这些
Properties
就会被设置为实例属性。我这样想对吗?

您已经在创建这样一个集合:

PropertyDescriptorCollection propsCollection = 
            new PropertyDescriptorCollection(instanceProps.Cast<PropertyDescriptor>().ToArray());
instanceProps.Cast<PropertyDescriptor>().Concat(customProperties).ToArray()
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
不仅描述了您的属性,还使客户端能够实际获取和设置这些属性的值。这就是重点,不是吗

propertyType
属性本身的类型正确吗?组件类型呢?它是属性所在的对象类型吗?
propertyType
是动态属性的类型。如果您有一个名为
Count
的动态整数属性,它将是
typeof(int)
componentType
是具有动态属性的类的类型,例如
typeof(MyDynamicPropertyClass)
。还有一个问题。这样,如果以前通过
Properties
列表添加的属性被动态访问(例如使用
var
),我可以确保
GetProperties()
被用于访问所述属性吗?不幸的是,不可以。只有在客户端(实际查找、读取和写入属性的实体)支持
TypeDescriptor
操作方式。这有时称为“组件模型”并非所有属性使用者都支持它。例如,WPF确实支持它,例如用于数据绑定。此外,WinForms支持
PropertyGrid
的组件模型。但在其他地方,属性只是属性,而组件模型不被使用。最简单的事情是看它是否适用于您的应用程序。
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; }
}