Frage

I recently discovered that a .NET attribute can only contain primitive types, strings, enums, objects, and single parameter arrays of these types as discussed here.

I have the need to accept an IDictionary<string, string> through a .NET attribute, but obviously I can't use IDictionary<string, string> for the above reason. So, I am here looking for alternatives that can work within these guidelines.

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

Two possible options I came up with are to use XML or JSON in the declaration (as a string on the .NET attribute), which can be easily serialized into IDictionary<string, string> for my application, but this turns the declaration into a lengthy error-prone string with no syntax checking.

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

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

What, if any, other alternatives are available that are more elegant/straightforward than this?

War es hilfreich?

Lösung

As far as I know, you can add an attribute several times (Edit: If you set AllowMultiple to true, as Robert Levy noted). So maybe instead of using one attribute with a whole dictionary, you could use several attributes, one for each dictionary entry, each with a key and a value parameter.

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

Andere Tipps

You can define an attribute that takes 2 string parameters (key and value) and AllowMultiple=true so that multiple instances of it can be applied to a type/member

While it is possible for you to specify the same Attribute class multiple times, it may be more beneficial to define each property as a separate, independent attribute.

For example VisibilityAttribute, MyAttributeAttribute, ... etc. You could then apply each attribute individually to properties.

If it seems cumbersome to reflect each manually, you could make a helper method that would reflect all the possible ones and return back a Dictionary object with each one's key/value.

For example:

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

Then you could have a helper method that does something like this:

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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top