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