What is the easiest way to intercept a method call to add functionality?

Suppose I have a repository that returns a Post s list. The repository interface has a GetAll() method that does what it offers.

Now, guided by the theory that I should not put the domain logic in the repository, I want to intercept calls to the specific GetAll() method so that I can add the following logic to the result of GetAll() :

 return GetAll().OrderByDescending(p => p.Posted).ToList(); 

The reason I want to intercept this is because (1) I do not want the client to not call the extension method ( OrderByDescending or some unnecessary wrapper of this), I want it to be called every time and (2 ) I do not want all my specific implementations to have to remember in order to get the result of GetAll() - I want this logic to be in one place external to any repository.

What is the easiest way to do this?

I already use StructureMap , so if I can intercept this, it could be a low cost option. But I don't think SM intercepts method calls, just instantiating an object?

Do I need to go to proxy or mixin template? Do I need to go all in with a dynamic proxy lock? Or is there another method I should consider, or perhaps a combination?

I am really interested in the specific sentence to my example above. I am new to AOP, so please be careful.

+6
mixins aop structuremap interceptor castle-dynamicproxy
source share
4 answers

Exited with the DynamicProxy option. It was easier to use than I thought.

All that is needed is a link using Castle.DynamicProxy; ...

A bit IInterceptor ...

 public class PostRepoInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { invocation.Proceed(); if (invocation.Method.Name.Equals("GetAll", StringComparison.InvariantCultureIgnoreCase)) invocation.ReturnValue = this.GetModifiedGetAllResult(invocation.ReturnValue); } private object GetModifiedGetAllResult(object getAllResult) { return Post.GetOrderedPosts((IList<Post>)getAllResult); } } 

Two new lines in the StructureMap configuration:

  public RepoRegistry() { var pg = new ProxyGenerator(); For<IPostRepository>() .EnrichAllWith(z => pg.CreateInterfaceProxyWithTarget<IPostRepository>(z, new PostRepoInterceptor())); } 

.. and everything is done. GetAll() now behaves the way I want. I can still use the interfaces as I know, and I saved all DRY and disconnected for DDD.

Thanks Sam and Andre .

+12
source share

AFAIK, StructureMap only intercepts the construction of the object, so with its help it will not work.

I donโ€™t know the castle, but I think the idea here is to use the Decorator template so that you can do it yourself without returning to a third-party library by following the steps described in the previous link.

Here's how I do it, since I'm not a big fan of AOP.

NTN

+2
source share

No, it cannot change the return value. However, you can access the target inner aspect to change the target property. Assuming you already have a repository installed, here is the code to add a post-processing aspect to change the target property.

 IRepository<decimal> Rep = new Repository(); IRepository<decimal> tpRep = (IRepository<decimal>)ObjectProxyFactory.CreateProxy(Rep, new String[] { "GetAll" }, null, new Decoration((x, y) => { Console.WriteLine("Entering " + x.GetType().ToString()); if (x.GetType().ToString() == "ThirdPartyHR.Repository") { List<decimal> decimals = ((Repository)x).RepList; IEnumerable<decimal> query = decimals.OrderByDescending(num => num, new SpecialComparer()).ToList<decimal>(); ((Repository)x).RepList = (List<decimal>)query; } }, null)); tpRep.GetAll(); List<decimal> lstRep = Rep.RepList; 

If necessary, I can send you the full working code. And, if possible, answer me in the article โ€œAdd Aspects to an Object Using a Dynamic Decoratorโ€, as I do not automatically receive a message here.

0
source share

There is an article Add Aspects for an Object Using a Dynamic Decorator .

It describes the approach of adding aspects to an object at runtime, rather than adding aspects to a class at design time. Sounds like this is what you want.

-one
source share

All Articles