开发者

How to inject Predicate and Func in Spring.net

I want to create an object with a constructor containing predicate and func objects in the xml 开发者_C百科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)


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.


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜