Корпоративная библиотека — Получение значения из выражения значения параметра

#dependency-injection #unity-container #enterprise-library #ioc-container

#внедрение зависимостей #unity-контейнер #корпоративная библиотека #ioc-контейнер

Вопрос:

Я пытаюсь преобразовать параметры конструктора типовой регистрации корпоративной библиотеки в набор пар ключ / значение (хэш-таблицу или идентификатор в целом).

Свойство ConstructorParameters является IEnumerableOf(ParameterValue), поэтому моя проблема заключается в том, как извлечь значения из каждого объекта ParameterValue.

Каждый объект ParameterValue содержит тип и выражение.

Например если значение параметра содержит: «EventLoggingEnabled = false», то я могу получить ключ (который является EventLoggingEnabled), используя выражение.Участник.Назовите, но я не могу найти способ получить значение (которое равно «false»).

Есть мысли?

Комментарии:

1. Я хочу кое-что прояснить — Типовые регистрации специфичны для Enterprise Library и НЕ специфичны для Unity.

2. Да, это правильно (я пропустил это, так как впервые увидел API). Я исправил заголовок вопроса (и сообщение).

Ответ №1:

Вы смотрели на реализацию UnityContainerConfigurator? Даже если вы не хотите использовать Unity, вы можете посмотреть, как там обрабатывается регистрация типов, и адаптироваться к Windsor API.

Обычно вам не нужно кодировать для необработанного класса ParameterValue и просматривать лямбда-выражения. На самом деле существует три подкласса:

  • ConstantParameterValue
  • ContainerResolvedParameter
  • ContainerResolvedEnumerableParameter

Значение ConstantParameterValue присваивается непосредственно в качестве свойства .Value. ContainerResolvedParameter используется, когда значение параметра должно быть введено контейнером, а ContainerResolvedEnumerableParameter используется, когда у вас есть коллекция, которую необходимо ввести. Каждый экземпляр ParameterValue на самом деле является одним из этих типов.

Итак, что вам следует сделать, это попытаться привести к каждому из них, а затем переключиться на основе фактического типа. Существует базовый класс утилиты ParameterValueVisitor, который позволяет вам реализовать шаблон Visitor поверх значений ParameterValues, чтобы сделать ваш код чище.

Итак, что я бы сделал, так это отбросил выбор через лямбды — вам не нужно этого делать. Внедрите программу visitor для извлечения необходимой вам информации с использованием базового класса, тогда предварительно обработанная информация будет доступна вам в конкретных классах. Посмотрите на UnityContainerConfigurator для примера того, как это делается.

Комментарии:

1. Я обязательно последую вашему совету, спасибо. (В этом конкретном проекте я не могу переключиться с Windsor на Unity, но это не значит, что мне это не нравится.) Еще раз спасибо за ответ.

2. Хорошо, я получил свои первые два, пройдя (или зеленый!) тесты на интеграцию!! Вот что я сделал до сих пор, github.com/moodmosaic/WindsorContainerConfigurator

Ответ №2:

Это работает, когда выражение не имеет значения ResolvedEnumerable.

     var dependencies = new Hashtable();

        foreach (ParameterValue pv in constructorParameters)
        {
            MemberExpression exp = pv.Expression as MemberExpression;
            if (exp != null)
            {
                String key = exp.Member.Name;
                Object val = GetValue(exp);

                dependencies.Add(key, val);
            }
        }

    // ...

    private Object GetValue(MemberExpression member)
    {
        var objectMember = Expression.Convert(member, typeof(Object));
        var getterLambda = Expression.Lambda<Func<Object>>(objectMember);

        return getterLambda.Compile().Invoke();
    }