Как ввести Predicate и Func в Spring.net - PullRequest
3 голосов
/ 12 августа 2011

Я хочу создать объект с конструктором, содержащим объекты предиката и func в конфигурации xml, используя spring. Аргументы Predicate и Func должны указывать на метод другого настроенного объекта. Как это возможно с помощью Spring.net? Я не смог найти решение или подсказку в документации ...

Пример конструктора будет:

MyClass(Predicate<TInput> condition, Func<TInput, TOutput> result)

Ответы [ 3 ]

3 голосов
/ 28 августа 2012

Можно также использовать DelegateFactoryObject в Spring.net для создания делегатов (Action, Func, Predicate являются только специальными делегатами):

  <object type="Spring.Objects.Factory.Config.DelegateFactoryObject, Spring.Core">
    <property name="DelegateType" value="System.Action"/>
    <property name="TargetObject" ref="MyTarget" />
    <property name="MethodName" value="MyDelegate" />
  </object>

Так что вам не нужно создавать такую ​​конструкциюMySpringConfigurationDelegateObjectContainer, упомянутый выше, для пересылки делегатов через фабричные методы.

2 голосов
/ 13 августа 2011

Я бы сказал, что вы должны извлечь предикат и функцию и поместить их в интерфейс. Затем вы можете использовать этот интерфейс в своем конструкторе. Если вы используете инъекцию конструктора в большинстве случаев, вы указываете зависимости как интерфейсы или типы. Конструктор в вашем примере использует 2 переменные экземпляра (в данном случае указывающие на метод).

Вы можете создать такой интерфейс:

public interface IInterface<TInput, TOutput>
{
    bool GetOutput(TInput item);
    TOutput GetResult(TInput item);
}

И используйте этот интерфейс в качестве параметра конструктора, который даст вам тот же результат, что и ваш «другой сконфигурированный объект» для реализации этого интерфейса.

0 голосов
/ 15 августа 2011

Я решил проблему, используя промежуточную «фабрику», вдохновленную предложением thekip, но оставив объект, требующий предикат и функцию в конструкторе (MyClass в примере выше), нетронутым. Это решение сохраняет «проблему» обработки делегатов весной за пределами реализации MyClass (вопреки предложению thekip, но спасибо за ваш ответ).

Вот мой способ настройки такой ситуации (настройка делегатов в Spring.Net с использованием фабричного шаблона на основе объектов).

MyDelegator class пример реализации для использования предиката / func (здесь объект, но может быть что-нибудь еще, подходящее для параметров предиката / функции):

public class MyDelegator
{
    // for the predicate Predicate<TInput> condition, implemented with object
    public bool Condition(object input) 
    {
        ...
    }

    //for the Func<TInput, TOutput> result, implemented with object
    public object Evaluate(object input) 
    {
        ...
    }
}

... тогда вам нужен контейнер для объекта с предикатом и или func (может быть в отдельных классах тоже) ...

public class MySpringConfigurationDelegateObjectContainer
{
    private readonly Predicate<object> condition;
    private readonly Func<object, object> evaluate;

    public MySpringConfigurationDelegateObjectContainer(MyDelegator strategy)
    {
        condition = strategy.Condition;
        evaluate = strategy.Evaluate;
    }

    public Predicate<object> GetConditionMethod()
    {
        return condition;
    }

    public Func<object, object> GetEvaluateMethod()
    {
        return evaluate;
    }
}

... и это можно настроить в Spring.Net xml следующим образом

  <!-- a simple container class, just has the object with the method to call -->
  <object id="Container" type="MySpringConfigurationDelegateObjectContainer">
    <constructor-arg name="myDelegateObject">
      <!-- put the object with the delegate/func/predicate here -->
      <object type="MyDelegator" />
    </constructor-arg>
  </object>

И теперь вы можете использовать это в любом месте вашей конфигурации для объектов с помощью предиката / функции. (не нужно менять класс, требующий предикат / func)

  <object id="NeedAPredicateAndFuncInConstructor" type="...">
    ...
    <constructor-arg name="condition">
      <object factory-method="GetConditionMethod" factory-object="Container" />
    </constructor-arg>
    <constructor-arg name="result">
      <object factory-method="GetEvaluateMethod" factory-object="Container" />
    </constructor-arg>
    ...
  </object>

Вот и все. Есть предложения по улучшению этого решения? Может быть, Spring.net уже имеет общее решение для этого ...

...