0

假设我有以下不允许更改的类:

public class BaseType
{
    public UInt32 m_baseMember = 1;
    public bool m_baseMemberBool = false;
}

public class ComposedType
{
    public ComposedType()
    {
        m_baseData = new BaseType();
    }
    public UInt32 m_newMember = 2;


    public BaseType m_baseData;
}

现在我想通过将它们放入 PropertyGrid 来编辑这些数据。我创建了两个像这样的 Wrapper 类(http://msdn.microsoft.com/en-us/magazine/cc163816.aspx

    public class FieldsToPropertiesProxyTypeDescriptor : ICustomTypeDescriptor 
{
    private object _target; 
    // object to be described 
    public FieldsToPropertiesProxyTypeDescriptor(object target) 
    { 
        if (target == null) 
            throw new ArgumentNullException("target"); 
        _target = target; 
    }

    public object GetProxiedObject()
    {
        return _target;
    }

    object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) 
    { 
        return _target; 
        // properties belong to the target object 
    }

    AttributeCollection ICustomTypeDescriptor.GetAttributes() 
    { 
        // Gets the attributes of the target object 
        return TypeDescriptor.GetAttributes(_target, true);
    } 

    string ICustomTypeDescriptor.GetClassName() 
    { 
        // Gets the class name of the target object 
        return TypeDescriptor.GetClassName(_target, true);
    }

    string ICustomTypeDescriptor.GetComponentName()
    {
        return TypeDescriptor.GetComponentName(_target, true);
    }

    TypeConverter ICustomTypeDescriptor.GetConverter()
    {
        return TypeDescriptor.GetConverter(_target, true);
    }

    EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
    {
        return TypeDescriptor.GetDefaultEvent(_target, true);
    }

    PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
    {
        return TypeDescriptor.GetDefaultProperty(_target, true);
    }

    object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
    {
        return TypeDescriptor.GetEditor(_target, editorBaseType);
    }

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
    {
        return TypeDescriptor.GetEvents(_target, attributes);
    }

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
    {
        return TypeDescriptor.GetEvents( _target );
    }

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() 
    {
        return ((ICustomTypeDescriptor)this).GetProperties(null); 
    }  

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties( Attribute[] attributes) 
    { 
        bool filtering = (attributes != null && attributes.Length > 0); 
        PropertyDescriptorCollection props = new PropertyDescriptorCollection(null);
        foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(_target, attributes, true)) 
        { 
            props.Add(prop); 
        }
        foreach (FieldInfo field in _target.GetType().GetFields()) 
        {             
            FieldPropertyDescriptor fieldDesc = new FieldPropertyDescriptor(field);
            if (!filtering || fieldDesc.Attributes.Contains(attributes)) 
                props.Add(fieldDesc);
        }                       
        return props; 
    } 
}

public class FieldPropertyDescriptor : PropertyDescriptor
{ 
    private FieldInfo _field; 
    public FieldPropertyDescriptor(FieldInfo field) : base(field.Name, (Attribute[])field.GetCustomAttributes(typeof(Attribute), true)) 
    { 
        _field = field; 
    } 

    public FieldInfo Field 
    { 
        get { return _field; } 
    } 

    public override bool Equals(object obj) 
    { 
        FieldPropertyDescriptor other = obj as FieldPropertyDescriptor; 
        return other != null && other._field.Equals(_field); 
    } 

    public override int GetHashCode() 
    { 
        return _field.GetHashCode(); 
    } 

    public override bool IsReadOnly 
    { 
        get { return false; } 
    }

    public override AttributeCollection Attributes
    {
        get
        {
            if (_field.FieldType.IsClass || _field.FieldType.IsArray)
            {                   
                Attribute[] expandable = new Attribute[1];
                expandable[0] = new ExpandableObjectAttribute();
                return AttributeCollection.FromExisting(base.Attributes, expandable);
            }
            return base.Attributes;
        }
    }

    public override void ResetValue(object component)
    {

    } 

    public override bool CanResetValue(object component) 
    { 
        return false; 
    } 

    public override bool ShouldSerializeValue(object component) 
    { 
        return true; 
    } 

    public override Type ComponentType 
    { 
        get { return _field.DeclaringType; } 
    } 

    public override Type PropertyType 
    { 
        get { return _field.FieldType; } 
    }

    public override object GetValue(object component) 
    {
        if (component is FieldsToPropertiesProxyTypeDescriptor)
        {
            FieldsToPropertiesProxyTypeDescriptor proxy = (FieldsToPropertiesProxyTypeDescriptor)component;
            return _field.GetValue(proxy.GetProxiedObject()); 
        }             
        return _field.GetValue(component); 
    } 

    public override void SetValue(object component, object value) 
    {
        if (component is FieldsToPropertiesProxyTypeDescriptor)
        {
            FieldsToPropertiesProxyTypeDescriptor proxy = (FieldsToPropertiesProxyTypeDescriptor)component;
            _field.SetValue(proxy.GetProxiedObject(), value);
            OnValueChanged(proxy.GetProxiedObject(), EventArgs.Empty);
            return;
        }  
        _field.SetValue(component, value); 
        OnValueChanged(component, EventArgs.Empty); 
    } 
}

我可以在 PropertyGrid 中查看和编辑“m_newMember”,但我需要通过 FieldsToPropertiesProxyTypeDescriptor 包装对“m_baseData”的访问。我怎么能做到这一点。或者有没有更好的方法将字段包装到属性中?

4

1 回答 1

0

您可以在运行时更改给定类的属性,而无需更改该类。因此,您可以编写一个自定义 TypeConverter 并将其设置为您的类,如下所示:

    TypeDescriptor.AddAttributes(typeof(ComposedType), new TypeConverterAttribute(typeof(FieldsExpandableObjectConverter)));
    TypeDescriptor.AddAttributes(typeof(BaseType), new TypeConverterAttribute(typeof(FieldsExpandableObjectConverter)));

使用以下 TypeConverter(重用您的 FieldDescriptor 类):

public class FieldsExpandableObjectConverter : ExpandableObjectConverter
{
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        List<PropertyDescriptor> properties = new List<PropertyDescriptor>(base.GetProperties(context, value, attributes).OfType<PropertyDescriptor>());
        if (value != null)
        {
            foreach (FieldInfo field in value.GetType().GetFields())
            {
                FieldPropertyDescriptor fieldDesc = new FieldPropertyDescriptor(field);
                {
                    properties.Add(fieldDesc);
                }
            }
        }
        return new PropertyDescriptorCollection(properties.ToArray());
    }
}
于 2013-05-21T07:59:21.207 回答