Saturday, March 28, 2009

Delegates in Unity - 1

The thought originally came to me when I encountered the stack overflow exception during the dependency resolution of inter-dependent objects in Unity (or any other service-lookup framework).

If you're not familiar with this problem, try creating two or more classes that require each other's services: for instance an AccountService and a LoanService. Then try to inject the dependencies at runtime using a dependency-injection framework like Unity. The iterative nature of this sort of lookup causes a stack overflow.

There are ways to avoid this problem which i won't be talking about in this post. However, what I will be talking about is reducing the scope of a service to the point of it being a single method, a delegate.

Before reading further and if you haven't, take a look at the differences between interfaces and delegates in this MSDN article. (if the link is stale, search for delegate instead of interfaces in MSDN):
http://msdn.microsoft.com/en-us/library/ms173173.aspx

If I define my services in terms of delegates, I can implement them in any grouping that I want: I can implement each delegate in a dedicated class, bundle all into one class, or try to logically group them in corresponding classes.
You can go from coarse-grained (all ine one class) to the finest-grained grouping (each delegate in its own class) of program logic.

Let's get started. First I tried Unity as is and susprisingly it handled delegates with no problem.

To register delegate implementations, register them as "instances". Here's an example:
1. Declare the delegate

public delegate void VoidMethod();

2. Implement it somewhere:

public class MethodImpl
{
public void VoidMethodImpl()
{
MarkAsCalled("VoidMethodImpl");
Trace.WriteLine("VoidMethodImpl was called");
}
}

3. Register the implementation for the delegate type:

DelegateTestSupport.MethodImpl impl =
new DelegateTestSupport.MethodImpl();
container.RegisterInstance<VoidMethod>(impl.VoidMethodImpl);

4. Try to resolve the delegate and call it:

container.Resolve<VoidMethod>()();

It works perfectly. It makes you gain a new sense of appreciation for the language and also the work put in Unity.

You could also implement the delegates on the fly, using anonymous delegates or Lambda expressions:

container.RegisterInstance<VoidMethod>(
delegate()
{
Debug.WriteLine("anonymous delegate was called");
}
);



So the next optional step is to try to intercept calls to your delegates using Unity Interception extension. You'd probably have some common, cross-cutting concerns that you have encapsulated and now ready to apply to qualified delegates.

Here's where I got stopped. None of the interceptors in Unity could intercept a call to delegates registered like above. At least I could'nt get them to work.

So how would one go about intercepting delegates registered in a container? That's discussed in the next post.

No comments:

Post a Comment