How to inject Predicate and Func in Spring.net

元气小坏坏 提交于 2019-12-18 06:59:49

问题


I want to create an object with a constructor containing predicate and func objects in the xml config using spring. The Predicate and the Func arguments should point to a method of another configured object. How is this possible using Spring.net? I was not able to find a solution or hint in the documentation...

A sample constructor would be:

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

回答1:


It is also possible to use the DelegateFactoryObject within Spring.net to create delegates (Action, Func, Predicate are only special delegates):

  <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>

So you're not forced to create a construct such the MySpringConfigurationDelegateObjectContainer mentioned above to forward the delegates through factory methods anymore.




回答2:


I would say you have to extract the predicate and the function and put them behind an interface. Then you can use this interface in your constructor. If your using constructor injection most of the times you specify the dependencies as interfaces or types. The constructor in your example uses 2 instance variables (in this case pointing to a method).

You could create an interface like this:

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

And use this interface as constructor param, which gives you the exact same result as you can have your 'other configured object' implement this interface.




回答3:


I solved the problem using an intermediate "factory" inspired by the suggestion of thekip but leaving the object requiring the predicate and func in the constructor (MyClass in the example above) untouched. This solution keeps the "problem" of handling delegates in spring outside of the implementation of MyClass (in opposite of the suggestion of thekip, but thanks for your answer).

Here is my way to configure such a situation (setting delegates in Spring.Net, using object based factory pattern).

The MyDelegator class a sample implementation for predicate/func to use (object here, but could be anything else fitting to the predicate/func params):

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) 
    {
        ...
    }
}

... then you need a container for the object with the predicate and or func (could be in seperate classes, too) ...

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

... and this can be configured in Spring.Net xml this way

  <!-- 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>

And now you can use this anywhere in your config for objects with predicate/func (no need to change the class requiring the predicate/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>

That's it. Any suggestions to improve this solution? Maybe, Spring.net already has a generic solution for this...



来源:https://stackoverflow.com/questions/7039144/how-to-inject-predicate-and-func-in-spring-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!