Словарь конфигурации для единства через XML - PullRequest
4 голосов
/ 01 марта 2011

Как я могу настроить словарь через XML с контейнером Unity? Это работает:

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

Но мне нужна возможность добавлять элементы в XML-конфигурации.

Ответы [ 3 ]

6 голосов
/ 02 марта 2011

В прошлый раз, когда я пытался это сделать, мне пришлось использовать собственный конвертер и изобрести собственный синтаксический анализатор для значений словаря. Я не помню, какое исследование привело меня туда, но вот регистрация и соответствующий класс конвертера.

<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);
    }
}
4 голосов
/ 01 марта 2011

Я думаю, что есть несколько проблем с конфигурацией, которую вы опубликовали:

  1. Похоже, вы пытаетесь зарегистрировать экземпляр вместо зарегистрировать отображение типа .Для этого вам нужно использовать элемент instance вместо элемента register .
  2. Синтаксис, который вы используете для указания универсального типа, неверен,Чтобы указать словарь правильный синтаксис должен быть:

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

Обратите внимание, что `2 обозначает универсальный тип как имеющий два параметра типа.

  1. Задание значения для вашего экземпляра достигается установкой значение атрибут.Это строковое значение, которое нужно каким-то образом преобразовать в последовательность пар ключ-значение для вашего словаря.Это не произойдет по умолчанию, к сожалению.Вам нужно будет написать собственный конвертер, который будет принимать строку и создавать ваши пары ключ / значение.Пример такого конвертера можно найти здесь .

В качестве заключительного замечания (и личного предпочтения), я действительно не фанат использования Unity для этого типасоздания объекта.Я обычно использую пользовательский файл конфигурации для любых нетривиальных настроек инициализации и строго использую Unity для регистрации сопоставлений типов для внедрения зависимостей.

0 голосов
/ 16 августа 2016

Я сам не пробовал, но, вероятно, вы можете зарегистрировать несколько экземпляров класса KeyValuePair, а затем ссылаться на них в массиве, используемом в качестве параметра конструктора IDictionary.

...