c# - 将多个属性组合为单个属性 - 合并属性

标签 c# .net winforms visual-studio windows-forms-designer

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

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

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

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

如果我可以像这样组合多个属性,那就太好了:

[Hidden(true)]
public new Boolean AllowDrop;

其中隐藏属性将包含上述所有属性。所以只有 1 行代码。

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

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

谢谢

最佳答案

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

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

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

这个想法将以这种方式工作,您为您的类型创建一个自定义类型描述符。在自定义类型描述符中,您返回类型属性的自定义属性描述符,而在属性描述符中,您返回属性的一组自定义属性。

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

IMetedataAttribute接口(interface)

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

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

示例元数据属性

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

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;
    }
}

属性描述符

自定义类型描述符将使用此类来提供属性的自定义属性列表:

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; }
    // }
}

类型描述符

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

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);
    }
}

类型描述符提供程序

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

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 进行装饰,并且该类本身已注册以使用我们的自定义类型描述符提供程序:

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

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

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

关于答案的一些注释

  • 这项任务可能并不像您想象的那么简单。但它正在发挥作用。
  • 这是一个冗长的答案,但包含一个完整的工作示例,说明如何将类型描述符应用于您的类型以提供自定义元数据。
  • 该方法不适用于使用反射而不是类型描述的引擎。但它完全可以与例如 PropertyGrid 控件一起使用,该控件与类型描述一起使用。

关于c# - 将多个属性组合为单个属性 - 合并属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38503146/

相关文章:

c# - 如何在 mvc3 web 应用程序中设置特定的路由

c# - 如何在 C# 中让系统服务在 (Services.msc) 下运行

vb.net - Convert.ToInt32 格式不正确

c# - 重写抽象方法时,我重新设置抽象是否正确?

c# - 如何检查在模拟对象上使用特定参数调用的方法?

c# - 如何在可移植框架中设置 ServicePointManager.DefaultConnectionLimit

VB.NET - 如何创建信息框

c# - 如何使用 Linq 实现 NextRcord 和 PreviousRecord 按钮?

.net - 有没有官方的 WCF 标志?

c# - 将 C# 库移植到 Windows Phone 8?