问题描述
标题几乎说明了一切.当我通过我的类进行一些反思时,MemberInfo.GetCustomAttributes() 方法是否会保留成员的属性顺序?官方文档并没有说什么.
The title pretty much says it all. When I'm doing some reflection through my classes, will the MemberInfo.GetCustomAttributes() method preserve the order of attributes on a member, or not? The official documentation does not say anything one way or the other.
如果您想知道我为什么需要这个,这里是完整的解释.现在提出的问题很长而且不需要,但也许有人可以为更大的问题想出一个替代解决方案,它不涉及依赖属性枚举顺序.
In case you're wondering why I would need this, here's the full explanation. It's lengthy and not needed for the question as it is posed now, but perhaps someone can come up with an alternative solution to the greater problem which does not involve relying on attribute enumeration order.
我正在尝试为预期具有相当长生命周期的 (ASP.NET) 应用程序创建一个灵活的框架.在整个过程中,它将获得许多必须从菜单中访问的表格.为了让开发人员的生活更轻松,我制作了一个 MenuItemAttribute
,您可以将其应用于表单的类.此属性在其构造函数中具有无限数量的字符串参数,允许开发人员指定表单在菜单中的确切位置.一个典型的使用示例类似于 [MenuItem("Company", "Clients", "Orders")]
这意味着菜单应该有一个项目Company",在该项目下会有一个项目客户",其下将有一个项目订单" - 然后将打开表单.如果需要,单个表单可以具有多个这些属性 - 然后可以从菜单中的多个位置访问它.
I'm trying to make a flexible framework for an (ASP.NET) application that is expected to have a pretty long lifetime. Over the course it will gain many forms that will have to be accessible from the menu. To make life easier for the developers to come I've made a MenuItemAttribute
which you can apply to a form's class. This attribute has an unlimited amount of string parameters in its constructor which allows a developer to specify where exactly will the form reside in the menu. A typical usage example would be something like [MenuItem("Company", "Clients", "Orders")]
which would then mean that the menu should have an item "Company" under which there would be an item "Clients" under which there would be an item "Orders" - which would then open the form. A single form can have several of these attributes if needed - it will then be acessible from several places in the menu.
显然,整个菜单是在运行时通过枚举我的程序集中的所有类并搜索该属性来构建的.但是最近我收到了一个请求,即菜单项应该以预定义的方式进行排序.具有相关功能的表单应在菜单中彼此相邻.请注意,这不是按字母排序,而是开发人员指定的预定义顺序.
Obviously the whole menu is built in runtime by enumerating through all the classes in my assemblies and searching for this attribute. However recently I've gotten a request that the menu items should be sorted in a predefined way. Forms that have related functionality should be next to each other in the menu. Note that this is NOT alphabetical sorting, but a predefined order that the developers specify.
这就带来了问题——如何在这些属性中指定顺序?由于一个 MenuItemAttribute
描述了整个层次结构,因此订单规范还应包括整个(或至少一部分)层次结构的订单号.仅较低层次的订单号是不够的.
This then brings the problem - how do I specify the order in these attributes? Since one MenuItemAttribute
describes a whole hierarchy, the order specification should also include order numbers for the whole (or at least a part) of the hierarchy. An order number for just the lower level of the hierarchy is not sufficient.
我可以创建另一个属性 - MenuItemOrderHintAttribute
,但是当有多个 MenuItemAttribute
时,这会带来问题.因此是最初的问题.
I could make another attribute - MenuItemOrderHintAttribute
, but that would then bring problems with cases when there is more than one MenuItemAttribute
. Hence the original question.
我还可以扩展 MenuItemAttribute
以获取两个数组或一个数组对,但这会使语法复杂很多.最后一个想法是我可以使字符串具有特殊格式,但恕我直言,这将是相当混乱的.
I could also extend the MenuItemAttribute
to take either two arrays or an array of pairs, but that then would complicate the syntax a lot. The last idea is that I could make the strings have special format, but that would be rather messy IMHO.
好的,我有另一个想法.让我们使用 Jon Skeet 建议的顺序.这将允许指定层次结构的最后一级的顺序,而不是更高的.但我可以修改该属性,使其不仅适用于类,还适用于程序集本身.在这种情况下,菜单项将没有关联的表单.在装配级别,这些属性可用于指定层次结构更高级别之间的顺序.
OK, I've got another idea. Let's use the ordering that Jon Skeet suggested. This will allow to specify the order for the last level of the hierarchy, not the higher ones. But I could modify the attribute so that it applies not only to classes, but also to the assembly itself. In this case the menu item would not have an associated form. At the assembly level these attributes could then be used to specify the ordering among higher levels of the hierarchy.
这是集中式和分散式菜单系统之间的权衡.有什么想法为什么这是个坏主意?
This is then a tradeoff between a centralized and decentralized menu system. Any thoughts why this would be a bad idea?
推荐答案
我会在 MenuItemAttribute 构造函数中添加一个额外的(可选)值,即order"或priority":
I'd put a single extra (optional) value in the MenuItemAttribute constructor, which is "order" or "priority":
[MenuItem(0, "Company", "Clients", "Orders")]
[MenuItem(1, "Foo", "Bar", "Baz")]
我并不是说它会很漂亮,但它可以有效地让您指定排序.
I'm not saying it would be pretty, but it would effectively allow you to specify the ordering.
这篇关于GetCustomAttributes() 是否保留 .NET 中的属性顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!