How can I spring.net inject in to methods?
Asked Answered
I

2

4

I posted to following on the spring.net forum but also hoped I may get some value views here:

I am looking at some advice as to how I might achieve the following requirement.

Firstly some background - I am using Spring.NET to achieve IOC depdenecny injection in to my asp.net c# multi tier web application. Injection is achieved via spring.net xml configuration file with all my development achieved by developing against interfaces and injecting in an interface implemented class where required. This all works fine for me. My knowledge would be intermediate level I believe.

I have ran in to the problem and looking to achieve a solution for it.

To take for example I have a class with several methods where they all retrieve from a database, data being cached for a period of time.

I want to have freedom to inject in to each method the characteristics of the caching eg. time for it to live in cache etc. So rather than inject in class to where its required, I also want to be able to inject values in to methods.

I could go along the approach of creating properties on the class for each method but this gets messay, or injecting in settings to my class. My preference is to control each method via spring injection.

So any ideas how this can be achieved as I expect it something than others may have encountered.

One possible idea that I have come up with is to somehow inject an attribute on to each of the method via spring with attribute having properties with the values that required in the method eg cache duration etc. Is this a feasible solution? If so, could anyone assist me with configuring such.

Or if anyone has any other ideas, it would be great.

Inch answered 11/7, 2011 at 23:52 Comment(0)
B
6

If you take bbaia's approach, it might look like the example below. It's a bit simplified, but you can apply it to your situation. Let's assume we have an interface IDoWorkForSomeTime with a single parameter time:

public interface IDoWorkForSomeTime
{
    void Work(int time);
}

It's implemented by TimeBoundWorker and AdvisedTimeBoundWorker:

public class TimeBoundWorker : IDoWorkForSomeTime
{
    public void Work(int time)
    {
        Console.WriteLine("Working for {0} hours", time);
    }
}

public class AdvisedTimeBoundWorker : IDoWorkForSomeTime
{
    /* *** Note The Attribute *** */
    [ChangeParameter]
    public void Work(int time)
    {
        Console.WriteLine("Working for {0} hours", time);
    }
}

Then we can configure an AOP proxy to change the time parameter at runtime, so that when we run the following program:

class Program
{
    static void Main(string[] args)
    {
        IApplicationContext ctx = new XmlApplicationContext("objects.xml");
        var worker = (IDoWorkForSomeTime)ctx.GetObject("plainWorker");
        var advisedWorker = (IDoWorkForSomeTime)ctx.GetObject("advisedWorker");

        worker.Work(4);
        advisedWorker.Work(4);
    }
}

It outputs:

Working for 4 hours
Working for 8 hours

So although I call it with value 4, advisedWorker uses the value 8, which I configured in my spring config file. The spring container sees the [ChangeParameter] attribute and knows from my configuration that it has to apply the following method interceptor:

public class ChangeParamInterceptor : IMethodInterceptor
{
    public int NewValue { get; set; }  // set in spring cofig

    public object Invoke(IMethodInvocation invocation)
    {
        invocation.Arguments[0] = NewValue; // change the argument
        object rval = invocation.Proceed();
        return rval;
    }
}

It requires this spring configuration in objects.xml:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">

  <object id="plainWorker"
          type="Examples.Aop.Shared.TimeBoundWorker, Examples.Aop.Shared"
          singleton="true">
  </object>

  <object id="advisedWorker"
          type="Examples.Aop.Shared.AdvisedTimeBoundWorker, Examples.Aop.Shared"
          singleton="true">
  </object>

  <!-- AOP configuration: -->

  <object id="changeParamAdvice"
          type="Examples.Aop.Shared.ChangeParamInterceptor, Examples.Aop.Shared">
    <!-- AH! there's the 8 -->
    <property name="NewValue" value="8" />
  </object>

  <object id="attributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop">
    <property name="Attribute" value="Examples.Aop.Shared.ChangeParameterAttribute, Examples.Aop.Shared" />
  </object>

  <object id="changeParamAspect" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
    <property name="Pointcut" ref="attributePointcut" />
    <property name="Advice" ref="changeParamAdvice"/>
  </object>

  <object id="ProxyCreator" 
          type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop" />     
</objects>

You have many more options for configuring AOP and applying advices such as ChangeParamInterceptor. Read more in the Spring.NET documentation on AOP.

Ballinger answered 15/7, 2011 at 13:5 Comment(0)
P
0

You can try using Spring.NET AOP. You can change method parameters at runtime.

Punctilious answered 12/7, 2011 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.