通过XML配置统一字典

时间:2011-03-01 12:10:50

标签: xml dependency-injection inversion-of-control unity-container

如何使用Unity容器通过XML配置字典? 这有效:

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

但我需要能够在XML配置中添加元素。

2 个答案:

答案 0 :(得分:6)

上次我尝试这样做时,我不得不使用自定义转换器并为字典值创建自己的解析器。我不记得哪个研究让我在那里,但这里是注册和相应的转换器类。

<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);
    }
}

答案 1 :(得分:4)

我相信您发布的配置存在一些问题:

  1. 您似乎正在尝试register an instance而不是register a type mapping。为此,您需要使用实例元素而不是寄存器元素。
  2. 用于指定泛型类型的语法不正确。要指定字典&lt; string,int&gt; ,正确的语法应为:

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

  3. 注意`2将泛型类型指定为具有两个类型参数。

    1. Specifying a value for your instance是通过设置属性来实现的。这是一个字符串值,必须以某种方式转换为字典的一系列键值对。遗憾的是,这不会发生。您需要编写一个自定义转换器,它将接受一个字符串并创建您的键/值对。可以找到这种转换器的示例here
    2. 作为最后一个注释(以及个人偏好),我真的不喜欢使用Unity来创建这种类型的对象。我通常使用自定义配置文件进行任何非平凡的初始化设置,并严格使用Unity来注册依赖注入的类型映射。