如何接受数据的“字典”作为自定义 .NET 属性参数?

Posted

技术标签:

【中文标题】如何接受数据的“字典”作为自定义 .NET 属性参数?【英文标题】:How can I accept a 'dictionary' of data as a custom .NET attribute parameter? 【发布时间】:2014-02-11 11:28:26 【问题描述】:

我最近发现 .NET 属性只能包含原始类型、字符串、枚举、对象和这些类型的单参数数组,如 here 所述。

我需要通过 .NET 属性接受IDictionary<string, string>,但显然由于上述原因我不能使用IDictionary<string, string>。所以,我在这里寻找可以在这些准则范围内工作的替代方案。

// I want to do this, but can't because of the CLR limitation
[MyAttribute(Attributes = new Dictionary   "visibility", "Condition1" ,  "myAttribute", "some-value"  )]

我想出的两个可能选项是在声明中使用 XML 或 JSON(作为 .NET 属性上的字符串),对于我的应用程序,可以轻松地将其序列化为 IDictionary<string, string>,但这反过来声明成一个冗长的容易出错的字符串,没有语法检查。

// XML
[MyAttribute(Attributes = "<items><item key='visibility' value='Condition1'/><item key='myAttribute' value='some-value'/></items>")]

// JSON
[MyAttribute(Attributes = " 'visibility': 'Condition1', 'myAttribute': 'some-value' ")]

还有什么比这更优雅/更直接的替代方案(如果有的话)?

【问题讨论】:

你为什么要传入一个字典,而不是为你的属性应该接受的每个“键”设置一组参数? @ScottChamberlain 因为我事先不知道键的名称是什么。它们是开发人员定义的。 【参考方案1】:

据我所知,您可以多次添加属性(编辑:如果您将 AllowMultiple 设置为 true,如 Robert Levy 所述)。因此,也许您可​​以使用多个属性,而不是对整个字典使用一个属性,每个字典条目一个,每个属性都有一个键和一个值参数。

[MyDictionaryEntry(Key = key1, Value = val1)]
[MyDictionaryEntry(Key = key2, Value = val2)]
[MyDictionaryEntry(Key = key3, Value = val3)]
[MyDictionaryEntry(Key = key4, Value = val4)]

【讨论】:

有趣的想法。不幸的是,这意味着我必须将现有自定义属性的这一属性变成一个单独的自定义属性——然后它们需要链接在一起。更不用说,它不是那么直观,因为应用程序中的每个其他地方都接受字典作为属性。除非我错过了什么……?这是我需要解决的问题:github.com/maartenba/MvcSiteMapProvider/blob/master/src/…【参考方案2】:

您可以定义一个带有 2 个字符串参数(键和值)和 AllowMultiple=true 的属性,以便可以将它的多个实例应用于一个类型/成员

【讨论】:

【参考方案3】:

虽然您可以多次指定相同的Attribute 类,但将每个属性定义为单独的独立属性可能更有益。

例如VisibilityAttributeMyAttributeAttribute、...等。然后您可以将每个属性单独应用于属性。

如果手动反映每个看起来很麻烦,您可以创建一个辅助方法来反映所有可能的,并返回一个带有每个键/值的 Dictionary 对象。

例如:

[Visibility("true")]
[MyAttribute("Something")]

然后你可以有一个辅助方法来做这样的事情:

static Dictionary<string, string> GetAttributeDictionary(object value)

  var dictionary = new Dictionary<string, string>();

  var type = value.GetType();
  var customAttributes = type.GetCustomAttributes(true);

  foreach (var attribute in customAttributes)
  
    if (attribute is VisibilityAttribute)
    
       var visibilityAttribute = attribute as VisibilityAttribute;
       dictionary["Visibility"] = visibilityAttribute.Visibility;
    

    // Process other custom attributes...
  

  return dictionary;

【讨论】:

我不知道属性键是什么,因为它们是开发人员定义的。然而,这给了我另一个想法——我可以使用一个接口来确定我感兴趣的属性类型,而那些定义接口的类型可以命名为最终开发人员想要的任何名称。并且类型的名称(减去后缀属性)可以用作结果字典中的键。它仍然不漂亮,因为我必须将我的一个自定义属性分解为 2,但如果我走这条路,至少会有编译时检查和智能感知。

以上是关于如何接受数据的“字典”作为自定义 .NET 属性参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Json.Net 序列化/反序列化带有自定义键的字典?

字典作为 ComboBox 的数据源

Core Data 中带有自定义对象的可转换集合

Json.net自定义字典格式

Objective-c:自定义类实例作为字典键,当键存在时返回 nil

Asp.Net WebApi 上的自定义授权属性