将多个属性组合为单个属性 - 合并属性 [英] Combining multiple Attributes to a single Attribute - Merge Attributes

查看:39
本文介绍了将多个属性组合为单个属性 - 合并属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个控件上,我使用了多个属性:

On a control I am using multiple attribute properties:

[Browsable(false)]
[Bindable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("", true)]
public new Boolean AllowDrop;

我也在许多其他控件属性上使用这些属性.

I am using those properties on a lot of the other control properties as well.

我想知道是否有办法减少每次编写的代码量.

I am wondering if there is a way to reduce the amount of code to write each time.

如果我能像这样组合多个属性就好了:

It would be nice if I could combine multiple attributes like this:

[Hidden(true)]
public new Boolean AllowDrop;

Hidden 属性将包括上述所有属性.所以只有 1 行代码.

Where the Hidden Property would include all the attributes above. So there is only 1 single line of code.

也许还有一种方法可以在宏或其他东西中组合属性?

Maybe there is also a way to combine the attributes in a macro or something?

我知道还有其他隐藏属性的方法,但我选择了使用属性的方式.

I am aware that there are other ways of hiding properties but I chose the way of using attributes.

谢谢

推荐答案

这取决于使用该属性的框架.

It depends to the framework which is using the attribute.

组合属性对于使用和解释属性的上下文可能是有意义的.例如,对于那些使用 .Net 类型描述机制的上下文,您可以自定义 类型描述 .Net 返回给消费者.

Combining attributes can be meaningful in order to the context which uses and interprets attributes. For example for those contexts which use .Net Type Description mechanisms you can customize the type description which .Net returns to consumers.

可以为此使用标准 .Net 机制为类型提供自定义元数据,为您的对象注册自定义类型描述符.

It's possible to provide custom metadata for types using the standard .Net mechanism for that purpose, registering a custom type descriptor for your object.

这个想法会这样运作,你为你的类型创建一个自定义的类型描述符.在自定义类型描述符中,您为您的类型的属性返回自定义属性描述符,在属性描述符中,您返回该属性的一组自定义属性.

The idea will work this way, you create a custom type descriptor for your type. In the custom type descriptor, you return custom property descriptors for the properties of your type and in the property descriptor, you return a custom set of attributes for the property.

该方法需要更多代码,但它确实很有趣,并且分享了一些关于如何为您的类型提供自定义元数据的好主意:

The approach requires more code, but it's really interesting and shares some good idea about how to provide custom metadata for your types:

IMetadataAttribute 接口

该用法提供了一种创建 MetaDataAttributes 的标准方法.实现此接口的每个属性都将用作元数据,而不是使用它在 Process 方法中返回的属性:

The usage is providing an standard way to create MetaDataAttributes. Each attribute which implements this interface will be used as metadata and instead of the attribute, those one which it returns in Process method will be used:

public interface IMetadatAttribute
{
    Attribute[] Process();
}

示例元数据属性

这是一个示例元数据属性,它在处理属性时返回一些属性:

It's a sample metadata attribute which returns some attribute instead when processing the attribute:

public class MySampleMetadataAttribute : Attribute, IMetadatAttribute
{
    public Attribute[] Process()
    {
        var attributes = new Attribute[]{ 
            new BrowsableAttribute(false),
            new EditorBrowsableAttribute(EditorBrowsableState.Never), 
            new BindableAttribute(false),
            new DesignerSerializationVisibilityAttribute(
                    DesignerSerializationVisibility.Hidden),
            new ObsoleteAttribute("", true)
        };
        return attributes;
    }
}

属性描述符

自定义类型描述符将使用该类为属性提供自定义属性列表:

This class will be used by the custom type descriptor to provide a custom list of attributes for the property:

public class MyPropertyDescriptor : PropertyDescriptor
{
    PropertyDescriptor original;
    public MyPropertyDescriptor(PropertyDescriptor originalProperty)
        : base(originalProperty) { original = originalProperty;}
    public override AttributeCollection Attributes
    {
        get
        {
            var attributes = base.Attributes.Cast<Attribute>();
            var result = new List<Attribute>();
            foreach (var item in attributes)
            {
                if(item is IMetadatAttribute)
                {
                    var attrs = ((IMetadatAttribute)item).Process();
                    if(attrs !=null )
                    {
                        foreach (var a in attrs)
                            result.Add(a);
                    }
                }
                else
                    result.Add(item);
            }
            return new AttributeCollection(result.ToArray());
        }
    }
    // Implement other properties and methods simply using return original
    // The implementation is trivial like this one:
    // public override Type ComponentType
    // {
    //     get { return original.ComponentType; }
    // }
}

类型描述符

这是为您的类型提供自定义描述的类型描述符.在此示例中,它使用自定义属性描述符为您的类的属性提供自定义属性集:

This is the type descriptor which provides a custom description for your type. In this example it uses custom property descriptors to provide custom attributes set for the properties of your class:

public class MyTypeDescriptor : CustomTypeDescriptor
{
    ICustomTypeDescriptor original;
    public MyTypeDescriptor(ICustomTypeDescriptor originalDescriptor)
        : base(originalDescriptor)
    {
        original = originalDescriptor;
    }
    public override PropertyDescriptorCollection GetProperties()
    {
        return this.GetProperties(new Attribute[] { });
    }
    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
                             .Select(p => new MyPropertyDescriptor(p))
                             .ToArray();
        return new PropertyDescriptorCollection(properties);
    }
}

类型描述符提供程序

这个类将在你的类型上方的属性中使用,以引入我们作为类型元数据引擎创建的自定义类型描述符:

This class will be used in the attribute above your type to introduce the custom type descriptor which we created as the metadata engine for the type:

public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
    public MyTypeDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(object))) { }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
                                                            object instance)
    {
       ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(objectType, instance);
       return new MyTypeDescriptor(baseDescriptor);
    }
}

示例类

这是我的示例类,它的 Name 属性使用 MySampleMetadataAttribute 修饰,并且类本身已注册为使用我们的自定义类型描述符提供程序:

Here is my sample class which its Name property is decorated using MySampleMetadataAttribute and the class itself is registered to use our custom type descriptor provider:

[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]
public class MySampleClass
{
    public int Id { get; set; }
    [MySampleMetadataAttribue]
    [DisplayName("My Name")]
    public string Name { get; set; }
}

要查看结果,只需创建类的实例并在 PropertyGrid 中查看结果:

To see the result it's enough to create an instance of the class and see the result in PropertyGrid:

var o = new MySampleClass();
this.propertyGrid1.SelectedObject = o;

关于答案的一些说明

  • 对于此类任务,可能并不像您预期​​的那么简单.但它正在起作用.
  • 这是一个冗长的答案,但包含一个完整的工作示例,说明如何将类型描述符应用于您的类型以提供自定义元数据.
  • 该方法不适用于使用反射而不是类型描述的引擎.但它完全适用于例如 PropertyGrid 控件,该控件适用于类型描述.
  • Probably it's not as simple as you expected for such task. But it's working.
  • It's a lengthy answer, but contains a complete working example of how you can apply type descriptors to your types to provide custom metadata.
  • The approach will not work for engines which use reflection instead of type description. But it's completely working with for example PropertyGrid control which works with type description.

这篇关于将多个属性组合为单个属性 - 合并属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆