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