Config dictionary for unity through XML

How to customize a dictionary via XML using a Unity container? It works:

<register type="System.Collections.Generic.Dictionary[string,int]" > <constructor> <param name="capacity"> <value value="10" /> </param> </constructor> </register> 

But I need to add elements to the XML configuration.

+4
source share
3 answers

I believe that there are several problems with the configuration you posted:

  • It seems you are trying to register an instance , not register a display type . To do this, you need to use an instance , not a register element.
  • The syntax you use to specify a generic type is incorrect. To specify the Dictionary <string, int> , the following syntax should be:

    type = "System.Collections.Generic.Dictionary`2 [[System.String, mscorlib], [System.Int32, mscorlib]], mscorlib"

Note that `2 denotes a generic type with two type parameters.

  • Specifying a value for your instance is achieved by setting the value attribute. This is a string value that must somehow be converted to a series of key value pairs for your dictionary. Unfortunately, this will not happen by default. You will need to write your own converter, which will take a string and create key / value pairs. An example of such a converter can be found here .

As a final note (and personal preference), I'm really not a fan of using Unity to create this type of object. I usually use a custom configuration file for any non-trivial initialization parameters and strictly use Unity to register type mappings for dependency injection.

+4
source

The last time I tried to do this, I had to use my own converter and invent my own parser for dictionary values. I don’t remember what kind of research I got, but here is the registration and the corresponding converter class.

 <type type="IRequestPolicy" mapTo="RequestPolicyCatalog, Assembly"> <constructor> <param name="dictionary" type="System.Collections.Generic.KeyValuePair`2[System.Int32,System.String][], mscorlib"> <array> <value value="1, 'unauthorized'" typeConverter="Assembly.IntStringKeyValueConverter, fore.Core"/> <value value="2, 'activation'" typeConverter="Assembly.IntStringKeyValueConverter, Quofore.Core"/> <value value="3, 'routing'" typeConverter="Assembly.IntStringKeyValueConverter, Quofore.Core"/> </array> </param> </constructor> </type> 
 public class IntStringKeyValueConverter : System.ComponentModel.TypeConverter { public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { return this.ConvertFrom(context, culture, value); } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string); } public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType) { return destinationType == typeof(KeyValuePair<int, string>); } public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { var comma = ((string)value).IndexOf(','); if(comma < 0) throw new InvalidOperationException("Invalid string, must contain ',' between values"); var number = int.Parse(((string)value).Substring(0, comma)); var str = ((string)value).Substring(comma).Trim(new[] { ',', '\'', ' ' }); return new KeyValuePair<int, string>(number, str); } } 
+6
source

I have not tried it myself, but you can probably register a bunch of instances of the KeyValuePair class and then refer to them in the array used as the parameter of the IDictionary constructor.

0
source

Source: https://habr.com/ru/post/1341801/


All Articles