通过 XML 配置 Unity 字典

发布于 2024-10-19 20:48:30 字数 310 浏览 7 评论 0原文

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

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

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

How can I configure a dictionary via XML with Unity container?
This works:

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

But I need ability to add elements in XML config.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

多像笑话 2024-10-26 20:48:30

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

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

Last time I tried to do that I had to use a custom converter and invent my own parser for dictionary values. I don't remember which research got me there, 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);
    }
}
回忆凄美了谁 2024-10-26 20:48:30

我相信您发布的配置存在几个问题:

  1. 您似乎正在尝试注册实例而不是注册类型映射。为此,您需要使用 instance 元素而不是 register 元素。
  2. 您用来指定泛型类型的语法不正确。要指定 Dictionary正确的语法应该是:

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

请注意,`2 指定泛型类型具有两个类型参数。

  1. 指定实例的值 是通过设置value属性来实现的。这是一个字符串值,必须以某种方式转换为字典的一系列键值对。不幸的是,默认情况下不会发生这种情况。您将需要编写一个自定义转换器,它将接受字符串并创建键/值对。此类转换器的示例可以在此处找到。

最后一点(也是个人偏好),我真的不喜欢使用 Unity 来创建此类对象。我通常使用自定义配置文件来进行任何重要的初始化设置,并严格使用 Unity 来注册依赖注入的类型映射。

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

  1. It appears you are trying to register an instance rather than register a type mapping. To do this you need to use the instance element rather than the register element.
  2. The syntax you are using to specify a generic type is not correct. To specify a Dictionary<string, int> the proper syntax should be:

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

Note the `2 designates the generic type as having two type parameters.

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

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

路弥 2024-10-26 20:48:30

我自己没有尝试过,但您可能可以注册一堆 KeyValuePair 类的实例,然后在用作 IDictionary 构造函数参数的数组中引用它们。

I did not try it myself, but probably you can register a bunch of instances of KeyValuePair class, and then reference them in array used as an IDictionary constructor parameter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文