如何使用属性向 C# 类添加可见信息?
我正在尝试向 C# 界面添加信息,并且我正在尝试使用属性添加此信息。
举例来说,我到处都有 int 参数,其中一些 int 参数是“行 ID”,一些是“列 ID”。我希望能够做到这一点:
namespace RowIdTest1
{
using System;
public class Class1
{
public int Get([RowId] int r, [ColumnId] int c) { return 3; }
public void Set([RowId] int r, [ColumnId] int c, int x) { return; }
}
[AttributeUsageAttribute(AttributeTargets.All)]
public class RowIdAttribute : System.Attribute { }
[AttributeUsageAttribute(AttributeTargets.All)]
public class ColumnIdAttribute : System.Attribute { }
}
这样当另一个程序员使用我的 DLL 并在 Visual Studio 中浏览到 Class1 时, 他或她会在“Class1(来自元数据)”窗口中看到这一点:
namespace RowIdTest1
{
public class Class1
{
public Class1();
public int Get([RowId] int r, [ColumnID] int c);
public void Set([RowId] int r, [ColumnID] int c, int x);
}
}
当我尝试时,属性根本不会出现。
我知道你可以用 ///- 注释来做这种事情。
我知道您可以在任何内容上使用 System.ComponentModel.DescriptionAttribute 类(尽管会出现方法的描述,但不会出现参数的描述)。
我是否对 C# 属性做了一些完全奇怪的事情?不当?疯狂的?
I am trying to add information to a C# interface, and I am trying to add this information using attributes.
Say for example, that I have int parameters everywhere, and some of these int parameters are "row IDs" and some are "column IDs". I'd like to be able to do this:
namespace RowIdTest1
{
using System;
public class Class1
{
public int Get([RowId] int r, [ColumnId] int c) { return 3; }
public void Set([RowId] int r, [ColumnId] int c, int x) { return; }
}
[AttributeUsageAttribute(AttributeTargets.All)]
public class RowIdAttribute : System.Attribute { }
[AttributeUsageAttribute(AttributeTargets.All)]
public class ColumnIdAttribute : System.Attribute { }
}
so that when another programmer uses my DLL and browses to Class1 in Visual Studio,
he or she would see this in the "Class1 (from metadata)" window:
namespace RowIdTest1
{
public class Class1
{
public Class1();
public int Get([RowId] int r, [ColumnID] int c);
public void Set([RowId] int r, [ColumnID] int c, int x);
}
}
When I try it, the attributes don't appear at all.
I know you can do this sort of thing with ///-comments.
I know that you can use the System.ComponentModel.DescriptionAttribute class on anything (although descriptions on methods will appear but descriptions on parameters will not appear).
Am I doing something totally weird with C# attributes? Inappropriate? Insane?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的。
您正在尝试使用属性来表达有关参数的业务领域事实。这不是属性的用途。属性用于表达有关编程语言机制的事实。也就是说,当您说:
这就是说类本身已过时,您不应再使用它,因为类已被不同的类替换。不要使用过时的属性来声明该类所代表的物理世界事物不能再制造和销售以获取利润。
特定参数代表行标识符是关于方法的业务的事实,而不是关于方法的机制。您应该在方法参数上添加属性,以表达“此参数有默认值”或“通过 COM 互操作调用时应按值编组此参数”或“此参数将在读取之前写入” -- 这些是关于参数作为编程语言中的变量的事实,而不是关于参数如何对业务流程中的某些概念进行建模的事实。
有关如何使用属性来表达有关机制而不是业务领域的事实的更多想法,请参阅我关于该主题的文章及其评论:
http://blogs.msdn.com/b/ericlippert/archive/2009/02/02/properties-vs-attributes.aspx
Yes.
You are trying to use an attribute to express a business domain fact about the parameter. That's not what attributes are for. Attributes are for expressing facts about the programming language mechanism. That is, when you say:
That is saying that the class itself is obsolete and that you should no longer use it because the class has been replaced with a different class. Do not use the obsolete attribute to state that the physical world thing that the class represents can no longer be manufactured and sold at a profit.
That a particular parameter represents a row identifier is a fact about the business of your method, not about the mechanism of the method. You should put attributes on method parameters that express things like "this parameter has a default value" or "this parameter should be marshalled by value when called via COM interop" or "this parameter is going to be written to before it is read from" -- those are facts about the parameter as a variable in a programming language, rather than facts about how the parameter models some concept in your business process.
For more thoughts on how to use attributes to express facts about mechanisms instead of business domains, see my article on the subject and the comments to it:
http://blogs.msdn.com/b/ericlippert/archive/2009/02/02/properties-vs-attributes.aspx
一般来说,使用属性的原因是因为您希望在运行时通过反射让程序获得有关类或其成员的某些信息。这与这个想法不符,所以我认为这是对属性的不恰当使用。
我认为给程序员一个微妙的提示,即您希望参数代表 rowId 的更优选方法是使用参数名称:
将其与 /// 注释结合起来,就像您提到的那样,您有一个非常有效的方法来告诉您所在阶层的消费者您的期望是什么。
最后,如果您确实想防止用户意外地以错误的顺序提供参数,您可以利用强类型。
这使得某人几乎不可能意外地混淆输入。 (请注意,我并不推荐这种模式:它带来了大量的开销,但带来的好处却很少。)
In general, the reason to use attributes is because you want to have certain information about a class or its members available to your program via reflection at runtime. This isn't in keeping with that idea, so I'd say it's an inappropriate use of attributes.
I think a more preferred way to give the programmer a subtle hint that you want the parameter to represent a rowId is to use the parameter name:
Couple this with /// comments, like you mention, and you have a pretty effective way to tell consumers of your class what your expectations are.
Finally, if you really want to prevent users from accidentally providing the arguments in the wrong order, you could leverage strong typing.
This would make it nearly impossible for someone to accidentally mix up the inputs. (Note that I am not recommending this pattern: It introduces a lot of overhead for very little benefit.)
不,你不能。为什么不直接说出参数的名称呢
?
No, you can't. Why not just name the arguments
?
我不得不说我不太明白这一点。您的库的用户(我假设)必须反编译您的类才能查看元数据,这是否很常见?为什么不直接为接口编写一些 XML 文档并将其与您的库一起提供呢?
I have to say I don't understand this very well. Is it common that users of your library (I assume) have to decompile your classes to look at the metadata? Why not just write some XML documentation for the interface and ship it with your library instead?
不知道这算不算“疯狂”。如果它不能按原样工作,也许可以将属性分配给某种数据结构内的嵌套项,然后可以将数据结构作为参数传递给函数。只是一个想法。
I don't know if it's "insane". If it isn't working as is, maybe, assign the attributes to nested items inside of some kind of data structure, and then maybe pass the data structure as a parameter to the function. Just one idea.