Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将多个属性组合到单个属性-合并属性_C#_.net_Winforms_Visual Studio_Windows Forms Designer - Fatal编程技术网

C# 将多个属性组合到单个属性-合并属性

C# 将多个属性组合到单个属性-合并属性,c#,.net,winforms,visual-studio,windows-forms-designer,C#,.net,Winforms,Visual Studio,Windows Forms Designer,在控件上,我正在使用多属性属性: [Browsable(false)] [Bindable(false)] [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Obsolete("", true)] public new Boolean AllowDrop; 我在很多其他控件属性上也使用了这些属性 我想知道

在控件上,我正在使用多属性属性:

[Browsable(false)]
[Bindable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("", true)]
public new Boolean AllowDrop;
我在很多其他控件属性上也使用了这些属性

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

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

[Hidden(true)]
public new Boolean AllowDrop;
其中,
Hidden
属性将包括上述所有属性。所以只有一行代码

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

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


谢谢

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

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

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

这个想法是这样的,您可以为您的类型创建一个自定义类型描述符。在自定义类型描述符中,返回类型属性的自定义属性描述符,在属性描述符中,返回属性的自定义属性集

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

IMeterDataAttribute接口

其用途是提供一种创建MetaDataAttributes的标准方法。实现此接口的每个属性都将被用作元数据,并且将使用它在
过程
方法中返回的属性来代替该属性:

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

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

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; }
    // }
}
示例类

下面是我的示例类,它的
名称
属性使用
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
    控件一起工作

可以使用类型描述符,但需要更多代码!你可能会发现这篇帖子很有用:@RezaAghaei谢谢你的链接-听起来很有希望。但是VS不编译代码。它抱怨MyPropertyDescriptor没有实现继承的抽象成员“System.ComponentModel.PropertyDescriptor.GetValue(object)”。请阅读该类实现中的注释代码;)@RezaAghaei谢谢:)@RezaAghaei是的,它非常有用。还有更多的代码要为它的声明编写。但一旦写了一次,我就可以在许多控件中使用它。这正是我想要的:)是否也可以朝相反的方向工作?因此,将上述属性(Browsable=false、Bindable=false、observate=true等)设置为默认值,并仅公开特定属性?@Tommy可能是的,可以这样做。看看这篇文章。在回答中,我将
DesignerSerializationVisibility
属性的默认值更改为
Hidden
,因此不具有
Visible
Content
属性的属性将不会序列化。您可能会发现喜欢的帖子很有用。@Tommy是的,完全有可能,我检查过了。我发现可以将IsBrowserable添加到MyPropertyDescriptor中。但是你怎么能覆盖过时的属性呢?@Tommy我通过覆盖
属性
属性来解决这个问题。因此,您可以添加/删除所需的任何属性。对于
browsableattribute
来说,结果是我所期望的。但是关于废弃属性,我不知道预期的结果是什么。
[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]
public class MySampleClass
{
    public int Id { get; set; }
    [MySampleMetadataAttribue]
    [DisplayName("My Name")]
    public string Name { get; set; }
}
var o = new MySampleClass();
this.propertyGrid1.SelectedObject = o;