ASP.NET MVC with Windsor – programmatic controller registration

March 28, 2009 at 11:29 AMAndre Loker

Although I’m a loyal MonoRail user, I’m playing with ASP.NET MVC a bit sometimes if time permits. One of the first things I wanted to do is using an IoC container such as Windsor to resolve controllers. ASP.NET MVC was built with extensibility in mind, so that’s not much of a problem, and it has been written about, for example by Matt Hall.

The problem is that the articles I read use the Windsor XML configuration for this. Frankly, I don’t like to configure my IoC container using XML if I don’t have to. Its syntax is pretty verbose and honestly I don’t need the controllers to be configured externally. Therefore, I prefer to use programmatic registration. Windsor has such a sweet registration API, you got to love it.

Alright, so what do you have to do to make programmatically registered controllers available to ASP.NET MVC?

Step 1 – create the container instance

This is easy: in the Application_Start event create the WindsorContainer and store it in a static(!) field. It has to be static, because more than one instance of the HttpApplication can potentially be created.

 

   1: public class MvcApplication : System.Web.HttpApplication {
   2:   static IWindsorContainer container;
   3:  
   4:   protected void Application_Start() {
   5:     CreateWindsorContainer();
   6:     RegisterRoutes(RouteTable.Routes); // has been there before!
   7:   }
   8:  
   9:   static void CreateWindsorContainer() {
  10:     container = new WindsorContainer();
  11:   }
  12: }

Did I mention that the container field needs to be static?

Step 2 – register controllers

This is where the nice API of Windsor comes into play. Extend the application as follows:

   1: public class MvcApplication : System.Web.HttpApplication{
   2:   ...
   3:  
   4:   protected void Application_Start() {
   5:     CreateWindsorContainer();
   6:     RegisterRoutes(RouteTable.Routes);
   7:     RegisterControllers(); // added
   8:   }
   9:  
  10:   ...
  11:  
  12:   static void RegisterControllers() {
  13:     container.Register(
  14:       AllTypes
  15:         .FromAssembly(Assembly.GetExecutingAssembly())
  16:         .BasedOn<IController>()        
  17:     );
  18:   }
  19: }

This is simple, isn’t it? No per-controller-entry in some XML file, just a simple piece of code.

Step 3 – create your own controller factory

To create the controller instances, ASP.NET MVC uses an object that implement IControllerFactory. So all we need to do is roll our own controller factory that uses Windsor and tell ASP.NET MVC to use that.

OK, so here’s our controller factory:

   1: public class WindsorControllerFactory : IControllerFactory {
   2:  
   3:   readonly IWindsorContainer container;
   4:  
   5:   public WindsorControllerFactory(IWindsorContainer container) {
   6:     this.container = container;
   7:   }
   8:  
   9:   public IController CreateController(RequestContext requestContext, string controllerName) {
  10:     var componentName = GetComponentNameFromControllerName(controllerName);
  11:     return container.Resolve<IController>(componentName);
  12:   }
  13:  
  14:   public void ReleaseController(IController controller) {
  15:     container.Release(controller);
  16:   }
  17:  
  18:   /// <summary>
  19:   /// Maps from a simple controller name to the name of the component
  20:   /// that implements the controller.
  21:   /// </summary>
  22:   /// <param name="controllerName">Name of the controller.</param>
  23:   /// <returns>Name of the controller component.</returns>
  24:   static string GetComponentNameFromControllerName(string controllerName) {
  25:     var controllerNamespace = typeof(HomeController).Namespace;
  26:     return string.Format("{0}.{1}Controller", controllerNamespace, controllerName);
  27:   }
  28: }

Nothing fancy here: first, we’ll need the windsor container instance, so we pass it as a constructor dependency. CreateController and ReleaseController are the two methods of IControllerFactory – their purpose should be self-explanatory. GetComponentNameFromControllerName maybe needs some further explanation. ASP.NET MVC will ask for controllers by their simple name, that is “Home” or “About” etc. However, by the way we registered the controller components Windsor knows them by their full type name, e.g. “MyApplication.Controllers.HomeController” and “MyApplication.Controllers.AboutController”. GetComponentNameFromControllerName simply converts from the simple controller name to the full component name.

Step 4 – tell ASP.NET MVC to use our controller factory

The last step is to tell ASP.NET MVC to actually use our IControllerFactory implementation instead of the default one. Conceptually this is easy, we only need to call ControllerBuilder.Current.SetControllerFactory and pass it either the type of our IControllerFactory implementation or an instance. But let’s not be too quick here and try to keep our application as DI-ish as possible. Here’s how I’d set the controller factory:

   1: public class MvcApplication : System.Web.HttpApplication{
   2:   ...
   3:  
   4:   protected void Application_Start() {
   5:     CreateWindsorContainer();
   6:     RegisterRoutes(RouteTable.Routes);
   7:     RegisterControllers();
   8:     RegisterControllerFactory(); // new
   9:   }
  10:   
  11:   void RegisterControllerFactory() {
  12:     container.Register(
  13:       Component
  14:         .For<IControllerFactory>()
  15:         .ImplementedBy<WindsorControllerFactory>()
  16:         .LifeStyle.Singleton
  17:       );
  18:     var controllerFactory = container.Resolve<IControllerFactory>();
  19:     ControllerBuilder.Current.SetControllerFactory(controllerFactory);
  20:   }
  21:  
  22:   static void CreateWindsorContainer() {
  23:     container = new WindsorContainer();
  24:     // new: register the container with itself 
  25:     //      to be able to resolve the dependency in the ctor
  26:     //      of WindsorControllerFactory
  27:     container.Register(
  28:       Component
  29:         .For<IWindsorContainer>()
  30:         .Instance(container)
  31:       );
  32:   }  
  33:  
  34:   ...
  35: }

You see, instead of new-ing an instance of WIndsorControllerFactory we register it as a singleton component and resolve it. Also note that we needed to register the Windsor container with itself to have the constructor dependency resolved.

Finally, here’s the complete source code of the global application class so far:

   1: public class MvcApplication : System.Web.HttpApplication {
   2:   static IWindsorContainer container;
   3:  
   4:   public static void RegisterRoutes(RouteCollection routes) {
   5:     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   6:  
   7:     routes.MapRoute(
   8:       "Default", // Route name
   9:       "{controller}/{action}/{id}", // URL with parameters
  10:       new { controller = "Home", action = "Index", id = "" } // Parameter defaults
  11:       );
  12:   }
  13:  
  14:   protected void Application_Start() {
  15:     CreateWindsorContainer();
  16:     RegisterRoutes(RouteTable.Routes);
  17:     RegisterControllers();
  18:     RegisterControllerFactory();
  19:   }
  20:  
  21:   static void CreateWindsorContainer() {
  22:     container = new WindsorContainer();
  23:     container.Register(
  24:       Component
  25:         .For<IWindsorContainer>()
  26:         .Instance(container)
  27:       );
  28:   }
  29:  
  30:   static void RegisterControllers() {
  31:     container.Register(
  32:       AllTypes
  33:         .FromAssembly(Assembly.GetExecutingAssembly())
  34:         .BasedOn<IController>()
  35:       );
  36:   }
  37:  
  38:   static void RegisterControllerFactory() {
  39:     container.Register(
  40:       Component
  41:         .For<IControllerFactory>()
  42:         .ImplementedBy<WindsorControllerFactory>()
  43:         .LifeStyle.Singleton
  44:       );
  45:     var controllerFactory = container.Resolve<IControllerFactory>();
  46:     ControllerBuilder.Current.SetControllerFactory(controllerFactory);
  47:   }
  48: }

Controller names and component names revisited

As you saw in step 3, we need to map the controller names to component names. This doesn’t take much effort and is my preferred way of handling this. But of course, you can already register the controller components with the respective controller names in the first place if you like. Just change the controller registration to something like this:

   1: static void RegisterControllers() {
   2:   container.Register(
   3:     AllTypes
   4:       .FromAssembly(Assembly.GetExecutingAssembly())
   5:       .BasedOn<IController>()
   6:       // modify the name with which the component is registered:
   7:       .Configure(component => component.Named(ControllerNameFromType(component.Implementation)))
   8:     );
   9: }
  10:  
  11: static string ControllerNameFromType(Type implementation) {
  12:   const string ControllerSuffix = "Controller";
  13:   var name = implementation.Name;
  14:   Debug.Assert(name.EndsWith(ControllerSuffix));
  15:   return name.Substring(0, name.Length - ControllerSuffix.Length);
  16: }

If you do this, you can remove the GetComponentNameFromControllerName method and simplify the implementation of IControllerFactory.CreateController to this:

   1: public IController CreateController(RequestContext requestContext, 
   2:                                     string controllerName) {
   3:   return container.Resolve<IController>(controllerName);
   4: }

Which version you choose is more or less a matter of taste. If you keep the full type name as the component’s name you reduce the chance for name clashes. However, if you register the components using the controller name creating the controller is slightly simpler.

More simplifications

You can even simplify the controller factory a bit if you inherit from DefaultControllerFactory instead of implementing IControllerFactory. Because DefaultControllerFactory will resolve the correct component type for you, you can simply override GetControllerInstance instead of implementing CreateController:

   1: public class WindsorControllerFactory : DefaultControllerFactory {
   2:   readonly IWindsorContainer container;
   3:  
   4:   public WindsorControllerFactory(IWindsorContainer container) {
   5:     this.container = container;
   6:   }
   7:  
   8:   protected override IController GetControllerInstance(System.Type controllerType) {
   9:     return container.Resolve(controllerType) as IController;
  10:   }
  11:  
  12:   public override void ReleaseController(IController controller) {
  13:     container.Release(controller);
  14:   }
  15: }

If you need to change the way that the controller name is mapped to a component type, you can also override GetControllerType.

MVC Contrib

As far as I know Windsor integration is also part of the MVC Contrib project. I haven’t looked into it, so bear with me if this article doubles existing code!

Posted in: ASP.NET | Castle

Tags: , , ,

Simple AOP: integrating interceptors into Windsor

February 20, 2009 at 3:47 PMAndre Loker

Aspect oriented programming (AOP) allows us to keep implement different concerns in isolation. In this article series I’ll describe ways to make use of AOP without much hassle. In the previous article of this serious we learned how to intercept method invocations using DynamicProxy2 and IInterceptors. However, we had to create the proxy instances manually. If you use Castle Windsor you can let the IoC container create the proxies and inject the interceptors.

I assume that you have used Castle Windsor or a different IoC container before. If not, check why you should use dependency injection.

Luckily Windsor integration of IInterceptors is a snap. In fact, you don’t have to add anything, it’s already been built in, because it has proven to be very useful. Because Windsor controls the instantiation of the registered components it was a logical consequence to add optional proxy creation and interface injection into that process. The Castle people are know what they do!

Basically, Windsor offers three ways to define interceptors that you want it to inject into components, ranging from rather static to fully dynamic.

Static injection with attributes

If all you want is the separation of concerns that injectors offer you and know which classes those aspects need to be applied to you can simply use the InterceptorAttribute.

Let’s start with a simple service interface and its implementation:

   1: public interface IService {
   2:     void DoSomething();
   3: }
   4:  
   5: public class Service : IService {
   6:     public void DoSomething() {
   7:         Console.WriteLine("Doing something");
   8:         throw new InvalidOperationException("Some exception thrown in DoSomething");
   9:     }
  10: }

And here’s the code that sets up Windsor for this service and creates an instance.

   1: var container = new WindsorContainer();
   2: container.Register(
   3:     Component.For<IService>().ImplementedBy<Service>()
   4: );
   5:  
   6: var service = container.Resolve<IService>();
   7: service.DoSomething();

As expected, running this piece of code will print “Doing something” and than fail with an uncaught exception. Now let’s say we want to add an aspect to the code that – in this simple case – prints a message to the console whenever an intercepted method throws an exception. Here’s the simple exception handling aspect from the previous article, which catches exception, prints an information message and optionally re-throws it.

   1: public class ExceptionAspect : IInterceptor {
   2:     public bool EatAll { get; set; }
   3:  
   4:     public void Intercept(IInvocation invocation) {
   5:         try {
   6:             invocation.Proceed();
   7:         } catch (Exception e) {
   8:             Console.WriteLine("{0} caught: {1}", e.GetType(), e.Message);
   9:             if (!EatAll) {
  10:                 throw;
  11:             }
  12:         }
  13:     }
  14: }

 

 

Two automatically inject this aspect into the Service component you only need to add two minor modifications:

1. Register the ExceptionAdvice as a component:

   1: container.Register(
   2:     Component.For<ExceptionAspect>()
   3:     .Parameters(Parameter.ForKey("EatAll").Eq("true"))
   4: );

 

2. Add the Castle.Core.InterceptorAttribute to the Service component:

   1: [Interceptor(typeof(ExceptionAspect))]
   2: public class Service : IService{
   3:     public void DoSomething() {
   4:         Console.WriteLine("Doing something");
   5:         throw new InvalidOperationException("Some exception thrown in DoSomething");
   6:     }
   7: }

This will tell Windsor to automatically create a proxy for the Service component and inject the interceptor of the given type (ExceptionAspect). Running the code now leads to the expected output:

image

Instead of a type you can also provide the key of a component to the InterceptorAttribute.

Simple dynamic injection

 

 

 

If you cannot or don’t want to use attributes – e.g. because you need to disable or enable certain aspects during configuration time – you can of course configure the Windsor container manually.

Let’s add a second aspect, namely a simple logging aspect that prints a message before and after the execution of intercepted methods. This is what our aspect looks like:

   1: public class LoggingAspect : IInterceptor {
   2:     public void Intercept(IInvocation invocation) {
   3:         Console.WriteLine("SomeInterceptor: Before method");
   4:         try {
   5:             invocation.Proceed();
   6:         } finally {
   7:             Console.WriteLine("SomeInterceptor: After method");
   8:         }
   9:     }
  10: }

Now we need to tell Windsor to inject the LoggingAspect into our Service. As with the ExceptionAspect we need to register the advice as a component:

   1: container.Register( Component.For<LoggingAspect>() );

Now we only need to change the registration of the service to inlcude the given aspect:

   1: container.Register(
   2:     Component
   3:     .For<IService>()
   4:     .ImplementedBy<Service>()
   5:     .Interceptors(InterceptorReference.ForType<LoggingAspect>()).Anywhere
   6: );

 

The only change is shown in line 5. The Interceptors() method expects an array of interceptors to apply to the component, Anywhere tells Windsor that we are not interested in the order in which multiple interceptors are applied (see below).

Running the application now yields:

image

 

If you configure the container in source code as shown above you can decide at configuration time which interceptors to inject. Of course, the interceptors can also be configured using an external XML file for full configurability.

If you configure multiple interceptors sometimes the order in which they are applied does matter. For example, assume you have an interceptor that caches method results and another one that secures the method for authorized access. In this case you will want the security interceptor to be applied before the caching interceptor, otherwise unauthorized user might see cached values that they are not allowed to see.  Windsor allows you to explicitly state the relative or absolute order of the configured interceptors.

  • ...Interceptors(interceptors).First
    The defined interceptors are prepended to the current list of interceptors.
  • ...Interceptors(interceptors).Last
    The defined interceptors are append to the current list of interceptors.
  • ...Interceptors(interceptors).AtIndex(x)
    The defined interceptors are inserted at the given index of the current list of interceptors.
  • ...Interceptors(interceptors).Anywhere 
    You don’t care where the interceptors are added.

Fully dynamic injection

You can even go one step further. Instead of defining the interceptors explicitly for the different components, Windsor allows you to install a hook that allows you to define the interceptors for each component on the fly during creation.

You can install that hook by implementing the interface IModelnterceptorsSelector which exposes two methods:

   1: public interface IModelInterceptorsSelector {
   2:     bool HasInterceptors(ComponentModel model);
   3:     InterceptorReference[] SelectInterceptors(ComponentModel model);
   4: }

Before a component is activated, Windsor calls HasInterceptor with the component model. If it returns true Windsor will invoke SelectInterceptors to request the actual interceptor references.

As an exammple, we’ll use another interceptor – TransactionAspect – that is injected with an IModelInterceptorSelector. First, here’s the interceptor:

   1: public class TransactionAspect : IInterceptor {
   2:     public void Intercept(IInvocation invocation) {
   3:         try {
   4:             Console.WriteLine("Opening transaction");
   5:             invocation.Proceed();
   6:             Console.WriteLine("Commit");
   7:         } catch (Exception e) {
   8:             Console.WriteLine("Rollback");
   9:             throw;
  10:         }
  11:     }
  12: }

And here’s our implementation of the IModelInterceptorsSelector:

   1: public class MyInterceptorSelector : IModelInterceptorsSelector {
   2:     public bool HasInterceptors(ComponentModel model) {
   3:         return typeof(TransactionAspect) != model.Implementation &&
   4:             model.Implementation.Namespace.StartsWith("SimpleAopWindsor");
   5:     }
   6:  
   7:     public InterceptorReference[] SelectInterceptors(ComponentModel model) {
   8:         return new[] { InterceptorReference.ForType<TransactionAspect>() };
   9:     }        
  10: }

As you see there’s nothing fancy going on here. HasInterceptors returns true for types in the SimpleAopWindsor namespace that are not TransactionAspect. The check for TransactionAspect is required in this specific case to prevent infinite recursion – otherwise, the TransactionAspect interceptor would be applied to itself.

SelectInterceptors simply returns an array of InterceptorReferences: in this case it contains only one element, ie. a reference to TransactionAspect.

Of course, we need to register the TransactionAspect as a component in Windsor:

   1: container.Register(
   2:     Component.For<TransactionAspect>()                
   3: );

And finally, we need to tell Windsor to use our interceptors selector.

   1: container.Kernel.ProxyFactory.AddInterceptorSelector(
   2:     new MyInterceptorSelector()
   3: );

If we run the application now we’ll see this:

image

What’s important here is the fact that our LoggingAspect and ExceptionAspect seem to be gone. This is important: if IModelInterceptorsSelector.SelectInterceptors returns a non-null array, only those interceptor will be used. Interceptors configured using one of the previously described methods (attributes or registration) will be ignored. If we want those interceptors to be applied as well our IModelnterceptorsSelector needs to return those references explicitly, eg. like this:

   1: public InterceptorReference[] SelectInterceptors(ComponentModel model) {
   2:     var interceptors = new List<InterceptorReference>(model.Interceptors.Count + 1);
   3:     // add all interceptors configured otherwise
   4:     foreach (InterceptorReference inter in model.Interceptors) {
   5:         interceptors.Add(inter);
   6:     }
   7:     // add an additional interceptor
   8:     interceptors.Add(InterceptorReference.ForType<TransactionAspect>());
   9:     
  10:     return interceptors.ToArray();
  11: }

Now our application uses all interceptors:

image

Conclusion

As you’ve seen there are many different ways to inject inspectors into components in a Windsor container, ranging from static definition of inspectors using attributes to fully dynamic injection using IModelInterceptorsSelector.

What’s missing in comparison toclassic” AOP frameworks such as AspectJ? Pointcuts of course! With IModelInterceptorsSelector we are able to choose which types get interceptors applied, but those interceptors intercept every method of the target. We’d like to be able to define something similar to pointcuts to select the methods that get intercepted. And that’s what’s the next article in this series will be about. Stay tuned!

Souce code for this article: SimpleAopWindsor.zip (600.79 kb)

Previous articles:

Posted in: C# | Castle | Patterns

Tags: , ,

Simple AOP: call interception with DynamicProxy

February 14, 2009 at 2:37 AMAndre Loker

Aspect oriented programming (AOP) allows us to keep implement different concerns in isolation. In this article series I’ll describe ways to make use of AOP without much hassle. After the introduction to AOP in the first article I’ll show how we can use Castle DynamicProxy to intercept method calls for the injection of advice code.

Introduction

If you’re reading this, you are probably interested in AOP and want to know how you can practise separation of concerns in you .NET application. There are quite some AOP frameworks available for .NET, so you might just grab the one that best fits your need. Below you’ll find an (incomplete!) overview of existing AOP frameworks for .NET

Examples for frameworks using compile time weaving/IL level manipulation:

Those frameworks weave the aspect code into compiled assemblies by modifying the IL code.

Examples for frameworks using proxy-based runtime weaving

The common technique behind those framework is this: for each class that needs to have advices applied to it the framework creates a subclass at runtime using the runtime code generation facilities of .NET. Each virtual call or interface method implementation is overridden. Those overridden methods can then redirect the call to the advices. As a result those frameworks normally only support a very small join point model, limited to the calls of virtual methods or interface methods. However, in many practical cases, this limitation is not that much of an issue.

Choose your destiny

Here we already have six frameworks to choose from. The question is: which one should I use or should I even use a different approach? I haven’t used all of those frameworks, so I can’t go into a detailed analysis of their commonalities and differences. Nevertheless, here are some general thoughts:

  1. If a specific concern is suitable for static weaving you probably want to go that way. As mentioned in the first article, compile time weaving has several benefits, especially allowing a much richer join point model and slightly less overhead.
  2. If you use Spring.NET or S2Container as your IoC container, using the respective AOP facility is probably the recommended way.
  3. If you need dynamic weaving and use the Castle stack read on, that’s what the rest of this article is about!

Castle facilities

Interestingly enough, Castle once had an AOP facility itself. It has been discontinued a while ago because apparently it wasn’t used much. It’s not that people find AOP as a concept useless, but it seems that a fully blown AOP framework is not required in many cases. Instead, people find a different facility to be sufficient, namely DynamicProxy2.

DynamicProxy2 (DP2) is a library that generates proxy types at runtime. DP2 supports different proxy strategies. In the case of AOP, two strategies are the most important:

  1. Create a class proxy: DP2 derives a proxy class from a given type.

class proxy

  1. Create an interface proxy with a target: instead of deriving from the target type, this strategy creates an implementation of one (or multiple) of the interfaces that the target type implements. This strategy resembles the classic Proxy pattern, because the instance created by DP2 replaces the target object.

interface proxy

Interceptors

Just creating new types at runtime is rather useless if that’s all. Of course, there is more. When you use DP2 to create the proxy instances you can provide one or more interceptors. An interceptor is an object implementing IInterceptor, which looks like this:

   1: public interface IInterceptor
   2: {
   3:     void Intercept(IInvocation invocation);
   4: }

Each virtual or interface method that the DP2 proxy generator overrides or implements respectively will call the Intercept() method of the interceptors you pass to the generator method. The IInvocation instance passed to the interceptor contains information about the method being intercepted:

   1: public interface IInvocation
   2: {
   3:     // Methods
   4:     object GetArgumentValue(int index);
   5:     MethodInfo GetConcreteMethod();
   6:     MethodInfo GetConcreteMethodInvocationTarget();
   7:     void Proceed();
   8:     void SetArgumentValue(int index, object value);
   9:  
  10:     // Properties
  11:     object[] Arguments { get; }
  12:     Type[] GenericArguments { get; }
  13:     object InvocationTarget { get; }
  14:     MethodInfo Method { get; }
  15:     MethodInfo MethodInvocationTarget { get; }
  16:     object Proxy { get; }
  17:     object ReturnValue { get; set; }
  18:     Type TargetType { get; }
  19: }

One of the most important members is Proceed() which will call the next IInterceptor for the current proxy or – if the current interceptor is the last one – it will invoke the “real” method.

DP2 in practice

Let’s put all this theoretic mumbo-jumbo into practice, shall we?

First, here’s our ultra complex domain model:

   1: // A service interface...
   2: public interface IService {
   3:   void DoSomething();
   4: }
   5:  
   6: // ... and its implementation
   7: public class Service : IService {
   8:   public void DoSomething() {
   9:     Console.Out.WriteLine("Service.DoSomething()");
  10:   }
  11: }

Nothing fancy here. Here’s our application code:

   1: public class Program {
   2:   public static void Main() {
   3:     IService service = CreateService();
   4:     service.DoSomething();
   5:   }
   6:  
   7:   private static IService CreateService() {
   8:     return new Service();
   9:   }
  10: }

If we run this – surprise – this is the result (the last line is “Press any key” in German)

image

Now we introduce DynamicProxy2. First off, add a reference to Castle.Core.dll and Castle.DynamicProxy2.dll.  Now we can write our first interceptor:

   1: public class LogInterceptor : IInterceptor {
   2:   public void Intercept(IInvocation invocation) {
   3:     Console.WriteLine("Intercepting {0}", invocation.Method.Name);
   4:   }
   5: }

Not bad so far. Finally, we need to inject the interceptor into the target. To do this, modify CreateService like this:

   1: private static IService CreateService() {
   2:   var dp = new ProxyGenerator();
   3:   var target = new Service();
   4:   var interceptor = new LogInterceptor();
   5:   return dp.CreateInterfaceProxyWithTarget<IService>(target, interceptor);
   6: } 

Now run the code again:

image

Wait, where’s “Service.DoSomething()”? We forgot one thing: if we don’t call Proceed() on the IInvocation object in Intercept(), the original method (or the next interceptor) won’t be called, so adjust the LogInterceptor like this:

   1: public void Intercept(IInvocation invocation) {
   2:   Console.WriteLine("Intercepting {0}", invocation.Method.Name);
   3:   // invoke next interceptor/intercepted method
   4:   invocation.Proceed();
   5: }

And voilá:

image

You see, calling Proceed() is necessary to have the intercepted method executed. This has several positive side effects:

  1. We can intentionally decide to block the call to the intercepted methods, for example for security reasons
  2. In the interceptor we can provide that has to be called before and after the execution of the intercepted method (“around advice” anyone?)
  3. We can “fork”, i.e. we can invoke the intercepted method multiple times

If we have more than one interceptor, calling Proceed() will only invoke the intercepted method if the current interceptor is the last one. Calling Proceed() in interceptors that are earlier in the chain will instead invoke the next interceptor. Here’s a collaboration diagram of a proxy with two interceptors:

image

Personally I think that having Proceed() do the right thing transparently is a wise choice.

The link to AOP

You’ve probably already noticed where this is going. We can use DP2 and the interceptors to implement our advices. Out advices are in fact implementations of IInterceptor and the ProxyGenerator acts as the weaver. Here’s another (not really useful) advice using IInterceptor:

   1: public class ExceptionAdvice : IInterceptor {
   2:  
   3:   public bool EatAll { get; set; }
   4:  
   5:   public void Intercept(IInvocation invocation) {
   6:     try {
   7:       invocation.Proceed();
   8:     } catch (Exception e) {
   9:       Console.WriteLine("{0} caught: {1}", e.GetType().Name, e.Message);
  10:       if (!EatAll) {
  11:         throw;
  12:       }
  13:     }
  14:   }
  15: }

Let’s add it into our case:

   1: private static IService CreateService() {
   2:   var dp = new ProxyGenerator();
   3:   var target = new Service();
   4:   var interceptor = new LogInterceptor();
   5:   // swallow all exceptions
   6:   var exceptionAdvice = new ExceptionAdvice {EatAll = true};
   7:   return dp.CreateInterfaceProxyWithTarget<IService>(target, interceptor, exceptionAdvice);
   8: }

If Service.SomeMethod now throws an exception we see this:

image

I’m sure you can come up with a bunch of more realistic concerns that could be implemented using IInterceptors.

Loose ends

Intercepting join points is probably one of the technically most difficult parts of an AOP framework. Luckily Castle DynamicProxy is a feasible tool for this. Let’s see how this intermediate solution compares to a “real” AOP framework:

  • All methods of the target are intercepted. Sometimes you want only a subset of the methods based e.g. on an attribute or the name of the method. Therefore the Intercept method needs to further filter invocations. It would be cool if we could somehow more declaratively define our pointcuts.
  • We have to explicitly generate the proxies with the interceptors. We’d like to have this done automatically. Luckily Castle Windsor, the IoC container of the Castle stack, has this feature built in, so we can make the interceptors part of the component model.
  • We can only intercept virtual methods or interface methods. Well, there’s not much we can do about it, this is an inherent problem of the proxy based weaving approach. If you need a richer join point model, have a look at frameworks supporting compile time weaving.
  • We currently only support around advices. That’s not too bad, given that it is the “mother” of all advices we can “derive” all kind of advice types. For example, you can provide a set of abstract advice classes from which the concrete advices are derived. Just derive from the correct advice type and implement the abstract method (decide for yourself whether this approach is useful for you):
   1: public abstract class AroundAdvice : IInterceptor {
   2:   void IInterceptor.Intercept(IInvocation invocation) {
   3:     Around(invocation);
   4:   }
   5:  
   6:   protected abstract void Around(IInvocation invocation);
   7: }
   8:  
   9: public abstract class BeforeAdvice : IInterceptor {
  10:   void IInterceptor.Intercept(IInvocation invocation) {
  11:     Before(invocation);
  12:     invocation.Proceed();
  13:   }
  14:  
  15:   protected abstract void Before(IInvocation invocation);
  16: }
  17:  
  18: public abstract class AfterAdvice : IInterceptor {
  19:   void IInterceptor.Intercept(IInvocation invocation) {
  20:     try {
  21:       invocation.Proceed();
  22:     } finally {
  23:       After(invocation);
  24:     }
  25:   }
  26:  
  27:   protected abstract void After(IInvocation invocation);
  28: }
  29:  
  30: public abstract class AfterReturningAdvice : IInterceptor {
  31:   void IInterceptor.Intercept(IInvocation invocation) {
  32:     invocation.Proceed();
  33:     AfterReturning(invocation);
  34:   }
  35:  
  36:   protected abstract void AfterReturning(IInvocation invocation);
  37: }
  38:  
  39: public abstract class AfterThrowingAdvice : IInterceptor {
  40:   void IInterceptor.Intercept(IInvocation invocation) {
  41:     try {
  42:       invocation.Proceed();
  43:     } catch (Exception e) {
  44:       AfterThrowing(invocation, e);
  45:     }
  46:   }
  47:  
  48:   protected abstract void AfterThrowing(IInvocation invocation, Exception e);
  49: }

Preview

The next part of the series will cover integration of interceptors into Castle Windsor. Have fun!

Attached you'll find the source code for this article.

DynamicProxyEx1.zip (243.14 kb)

Other articles in this series:

Posted in: Castle | Design | Snippets

Tags: , , , , , ,

Getting rid of strings (3): take your app settings to the next level

September 5, 2008 at 1:23 PMAndre Loker

In the previous parts of this series (part 1, part 2) I talked about the problems with literal strings in source code and presented different strategies to avoid those problems. In this episode I'll explain how we can abstract from app settings and leverage the power of the Castle DictionaryAdapter to improve the way our applications access their app settings.

Basics

Probably the easiest way to make certain aspects of a .NET application configurable is by using app settings. You can define app settings by adding (or augmenting) an <appSettings> section to your web.config or app.config, depending on the project type. This could look something like this:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <appSettings>
   4:     <add key="MaxUsers" value="20"/>
   5:     <add key="FeedbackMail" value="foo@localhost"/>
   6:   </appSettings>
   7: </configuration>

[As a small side note: you don't have to physically keep the appSettings section in the web.config/app.config file - read Keep your .config clean with external config files to learn how to move settings outside of the config file.]

To access the settings easily use the configuration API exposed by ConfigurationManager, specifically the AppSettings property. Here's a tiny app that accesses the values from the appSettings section:

   1: using System;
   2: using System.Configuration;
   3:  
   4: public class Program {
   5:   private static void Main() {
   6:     string feedbackMail = ConfigurationManager.AppSettings["FeedbackMail"];
   7:     int maxUsers = int.Parse(ConfigurationManager.AppSettings["MaxUsers"]);
   8:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   9:     Console.WriteLine("Max users: {0}", maxUsers);
  10:   }
  11: }

As you see, that's fairly simple. Some points of interest:

  • ConfigurationManager lives in System.Configuration. You need to add the assembly System.Configuration.dll to your project to use this class
  • AppSettings has two indexers:
    • One indexer accepts a string: the string provided should be one of the keys as defined in the appSettings section. The value returned is the content of the value attribute of the respective appSettings entry or null if the key wasn't found. Keys are case insensitive by the way, so AppSettings["feedbackMAIL"] returns the same value as AppSettings["FeedbackMail"]. Note, however, that white space before or after the key does count, so AppSettings[" FeedbackMail"] will return null. Also be sure to check your config file for accidentally added white space within the key attribute if your app does not find certain keys.
    • The other indexer accepts an integer, which is the index of the app setting to return. Granted, I don't see much use for that indexer.
  • The values returned by the indexers are always strings. Therefore, if you want to have an app setting as an integer you'll need to parse it.

Let's analyse this basic approach:

  • We use strings to index the AppSettings property which - as you should know by now - is very problematic.
    • If you misspell the key, the value returned is null, but you won't notice it before runtime.
    • If you change the key in the app settings, you'll have to update all references to that key in your code. Remember that strings are hard to refactor.
  • Values are always returned as strings so you need to parse them if you need data of a type other than string

Improving the situation

If you read the first article of this series you know that there are two basic steps that can improve the situation:

  1. Avoid spreading literals all over the code, define and use constants instead
  2. Hide any string dependent code behind an appropriate API

Applying those rules might lead you to the idea to write a class that encapsulates the app settings. A good idea indeed! Here's a class that encapsulates the app settings of our tiny example:

   1: class MySettings {
   2:   // constants that define the keys in the app settings
   3:   private const string MaxUsersKey = "MaxUsers";
   4:   private const string FeedbackMailKey = "FeedbackMail";
   5:  
   6:   public static string FeedbackMail {
   7:     get { return ConfigurationManager.AppSettings[FeedbackMailKey]; }
   8:   }
   9:  
  10:   public static int MaxUsers {
  11:     get { return int.Parse(ConfigurationManager.AppSettings[MaxUsersKey]); }
  12:   }
  13: }

I made the properties static because the class is stateless. Now you can access the settings like this:

   1: public class Program {
   2:   private static void Main() {
   3:     string feedbackMail = MySettings.FeedbackMail;
   4:     int maxUsers = MySettings.MaxUsers;
   5:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   6:     Console.WriteLine("Max users: {0}", maxUsers);
   7:   }
   8: }

This is much better! The strings are neatly hidden, so is the parsing of the integer. You can refactor the names of the properties easily using the refactoring tool of your choice.

Is this solution the final answer? Certainly not. This solution still suffers from some issues :

  • It's tedious to add and implement properties and possible parsing manually for each setting in the app settings section.
  • The settings are now strictly tied to ConfigurationManager. It's difficult to mock some app settings for unit testing using this approach.

Let me elaborate on the second issue: assume you have a class that is responsible for sending an email to the system administrator in case of an error. Here's a possible excerpt of such a system:

   1: // an interface we use to abstract sending of emails.
   2: public interface IMailSender {
   3:   void Send(string to, string subject, string text);
   4: }
   5:  
   6: // Sends error reports by mail
   7: public class ErrorReporter {
   8:   private readonly IMailSender mailSender;
   9:  
  10:   public ErrorReporter(IMailSender mailSender) {
  11:     this.mailSender = mailSender;
  12:   }
  13:  
  14:   public void SendErrorReport(string text) {
  15:     var email = MySettings.FeedbackMail;
  16:     mailSender.Send(email, "Application error", text);
  17:   }
  18: }
  19:  

It's certainly nice that we did not hardcode the email address that the report is sent to. But if we were to unit test the method we'd have to provide a value for the FeedbackMail app setting. (I'm using Rhino Mocks by the way)

   1: [Test]
   2: public void SendErrorReport_UsesMailSender() {
   3:   var mailSender = MockRepository.GenerateMock<IMailSender>();
   4:  
   5:   var text = "test message";
   6:   var email = "foo@localhost";
   7:  
   8:   // need to inject the email into the app settings
   9:   ConfigurationManager.AppSettings["FeedbackMail"] = email;
  10:  
  11:   var reporter = new ErrorReporter(mailSender);
  12:   reporter.SendErrorReport(text);
  13:  
  14:   mailSender.AssertWasCalled(x=>x.Send(email, "Application error", text));
  15: }

To make the test work we need to inject the expected email address into the app settings. I personally think that this situation is awkward and does certainly not isolate the unit test around one class under test. ErrorReporter uses MySettings which again uses ConfigurationManager. For my taste the number of classes involved in this unit test is unnecessarily high.

A solution

If you've never heard of Castle DictionaryAdapter, go and read my article on it, because this little tool will improve our solution a lot.

Here's what we do:

  • Delete MySettings, we won't use it anymore
  • Create instead an interface that represents your app settings:
   1: public interface ISettings {
   2:   int MaxUsers { get; }
   3:   string FeedbackMail { get; }
   4: }
  • Create a dictionary adapter that handles all the plumbing between ISettings and AppSettings:
   1: var factory = new DictionaryAdapterFactory();
   2: var adapter = factory.GetAdapter<ISettings>(ConfigurationManager.AppSettings);
  • Use this object instead of MySettings:
   1: public class Program {
   2:   private static void Main() {
   3:     var factory = new DictionaryAdapterFactory();
   4:     var settings = factory.GetAdapter<ISettings>(ConfigurationManager.AppSettings);
   5:     var feedbackMail = settings.FeedbackMail;
   6:     var maxUsers = settings.MaxUsers;
   7:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   8:     Console.WriteLine("Max users: {0}", maxUsers);
   9:   }
  10: }

Again, we have a type safe interface for our app settings. But what did we gain?

First we have to use much less code to define the interface for our app settings: ISettings is a no-brainer, just define properties with the desired type and the name matching the app settings key [see this article on DictionaryAdapter to learn how this can be configured in detail]. The DictionaryAdapter will handle all necessary lookup and conversion for you. Less code on our side is A Good Thing™.

Secondly by using an interface we have created a better abstraction of the app settings. Combine this with the power of dependency injection and you've created a basis for well testable, highly configurable code. If you don't see what I mean, read on and let me elaborate.

Why this solution rocks

First of all change ErrorReporter to accept an ISettings instance and use it instead of MySettings:

   1: public class ErrorReporter {
   2:   private readonly IMailSender mailSender;
   3:   private readonly ISettings settings;
   4:  
   5:   // Inject ISettings as well
   6:   public ErrorReporter(IMailSender mailSender, ISettings settings) {
   7:     this.mailSender = mailSender;
   8:     this.settings = settings;
   9:   }
  10:  
  11:   public void SendErrorReport(string text) {
  12:     var email = settings.FeedbackMail; // use ISettings instead of MySettings
  13:     mailSender.Send(email, "Application error", text);
  14:   }
  15: }

Two changes have taken place: I inject the ISettings dependency through the constructor and I use this object to access the email address.

ISettings in action - unit test

Here's the updated version of the unit test from above:

   1: [Test]
   2: public void SendErrorReport_UsesMailSender() {
   3:   var mailSender = MockRepository.GenerateMock<IMailSender>();
   4:  
   5:   var text = "test message";
   6:   var email = "foo@localhost";
   7:  
   8:   // create a stub for ISettings
   9:   var settings = MockRepository.GenerateStub<ISettings>();
  10:   // let this stub's FeedbackMail property return a specific value
  11:   settings.Stub(x => x.FeedbackMail).Return(email);
  12:  
  13:   // inject the settings
  14:   var reporter = new ErrorReporter(mailSender, settings);
  15:   reporter.SendErrorReport(text);
  16:  
  17:   mailSender.AssertWasCalled(x=>x.Send(email, "Application error", text));
  18: }

This approach is far superior to the old approach because we only have to stub a direct dependency of ErrorReporter (ie. ISettings). There's no need to configure an indirect dependency like ConfigurationManager.AppSettings. Furthermore we could now make an ISettings mock to check whether ErrorReporter really uses the settings object. Short, we have the full control of the behaviour of the ISettings instance.

ISettings in action - the real app

To use ISettings and ErrorReporter in a real app, we'd preferably use an IoC container like Castle Windsor to configure the ErrorReporter instance.

Here's how you could configure the container:

   1: var container = new WindsorContainer();
   2: // we'll need an implementation of IMailSender
   3: container.Register(Component.For<IMailSender>().ImplementedBy<SomeClassImplementingIMailSender>());
   4:  
   5: // create the adapter
   6: var adapter = new DictionaryAdapterFactory().GetAdapter<ISettings>(ConfigurationManager.AppSettings);
   7: // register this adapter instance as the component for ISettings
   8: container.Register(Component.For<ISettings>().Instance(adapter));
   9:  
  10: // and finally register the error reporter
  11: container.Register(Component.For<ErrorReporter>());

Whenever we need an instance of ErrorReporter now we can ask the container for it (object locator approach):

   1: var reporter = container.Resolve<ErrorReporter>();
   2: reporter.SendErrorReport("Something went horribly wrong");

Alternatively you could let the IoC container inject an ErrorReporter instance where you need it (dependency injection approach).

Both ways we'll get an ErrorReporter instance that is readily configured to access the app settings in a transparent way.

Conclusion

By using the proposed combination of

  1. an interface defining the app settings
  2. a dictionary adapter that maps between the AppSettings and the interface and
  3. an IoC container that can inject the adapter wherever we need it

we were able to completely get rid of any app settings related strings and created an architecture that is easily configurable and well testable.

By abstracting from the appSettings in the app.config file it's also easy to use a different configuration source instead. DictionaryAdapter can wrap all kinds of dictionaries and NameValueCollections. And if you come to the conclusion that you'd rather want to store the app settings in a database, it's easy to do, as well. Instead of using the DictionaryAdapter you could implement ISettings in a way that loads app settings from a database.

Posted in: C# | Patterns

Tags: , , , ,

Castle DictionaryAdapter

June 10, 2008 at 3:02 PMAndre Loker

DictionaryAdapter is a component of the Castle stack which can create an adapter between an interface and a dictionary at runtime. The DictionaryAdapter combines the flexibility of a dictionary with the type safety and convenience provided by a strong API. Here's an example:

   1: // the interface that will be used to access the content of the dictionary
   2: public interface ISimple {
   3:   string Name { get; set; }
   4:   int Age { get; set; }
   5: }
   6:  
   7: //...
   8:  
   9: // the backing store
  10: IDictionary dict = new Hashtable(); 
  11:  
  12: // dynamically create an adapter around dict 
  13: ISimple wrapper = new DictionaryAdapterFactory().GetAdapter<ISimple>(dict);
  14: wrapper.Name = "Andre"; // will be written to dict["Name"];
  15: wrapper.Age = 26;       // will be written to dict["Age"];
  16:  
  17: Assert.AreEqual("Andre", dict["Name"]);
  18: Assert.AreEqual("Andre", wrapper.Name);
  19:  
  20: Assert.AreEqual(26, dict["Age"]);
  21: Assert.AreEqual(26, wrapper.Age);

How to get the DictionaryAdapter

The DictionaryAdapter can be downloaded as part of the Castle project:

How does it work?

Calling DictionaryAdapterFactory.GetAdapter will create a new type on the fly. This type implements the interface that was provided as the type argument (here: ISimple). For each property on the interface a getter and/or setter will be implemented that reads a value from the provided dictionary or writes a value to the dictionary. The key that is used is based on the property name (the default setting is to use the property name as the key, later we will see how we can influence the key being used).

Creating an adapter is rather costly. It requires the creation of a new in-memory assembly containing the dynamic adapter type. However, this performance only exists the first time GetAdapter is called for a specific type. Subsequent requests for the same adapter type will reuse the generated assembly.

More examples and options

DictionaryAdapter has plenty of options to customize how the mapping between the adapter interface and the underlying dictionary happens. In this section I'll give some examples of what DictionaryAdapter is capable of without covering every detail (for a complete reference I'd recommend the Castle source code).

I will provide code examples in the form of an MbUnit test with the following skeleton:

   1: using System.Collections;
   2: using MbUnit.Framework;
   3: using Castle.Components.DictionaryAdapter;
   4:  
   5: [TestFixture]
   6: public class DictionaryAdapterTests {
   7:   private DictionaryAdapterFactory factory;
   8:   private IDictionary dict;
   9:  
  10:   [SetUp]
  11:   public void SetUp() {
  12:     factory = new DictionaryAdapterFactory();
  13:     dict = new Hashtable();
  14:   }
  15: }

The IDictionary instance is used as the backing store for which an adapter will created. The factory handles the dynamic creation of the adapters.

Download the source code of the examples (DictionaryAdapterTests.cs)

Basic example

Ones again, here's the most basic example:

   1: public interface ISimple {
   2:   string Name { get; set; }
   3:   int Age { get; set; }
   4: }
   5:  
   6: [Test]
   7: public void SimpleTest() {
   8:   var wrapper = factory.GetAdapter<ISimple>(dict);
   9:   wrapper.Name = "Andre";
  10:   wrapper.Age = 26;
  11:  
  12:   Assert.AreEqual("Andre", dict["Name"]);
  13:   Assert.AreEqual(26, dict["Age"]);
  14: }

Type prefix

Especially if you want to use multiple adapters on the same dictionary naming collisions can occur if a property with the same name is present in more than one adapter interface. To avoid this problem you can specify key prefixes using attributes. One possible prefix is the (full) name of the interface type:

   1: [DictionaryTypeKeyPrefix]
   2: public interface IWithTypePrefix {
   3:   string Name { get; set; }
   4:   int Age { get; set; }
   5: }
   6:  
   7: [Test]
   8: public void WithTypePrefix() {
   9:   var wrapper = factory.GetAdapter<IWithTypePrefix>(dict);
  10:   wrapper.Name = "Andre";
  11:   wrapper.Age = 26;
  12:  
  13:   Assert.AreEqual("Andre", dict[typeof (IWithTypePrefix).FullName + "#Name"]);
  14:   Assert.AreEqual(26, dict[typeof (IWithTypePrefix).FullName + "#Age"]);
  15: }

Custom prefix

The type prefix can be quite lengthy, so you might prefer setting your own prefix:

   1: [DictionaryKeyPrefix("My")]
   2: public interface IWithCustomPrefix {
   3:   string Name { get; set; }
   4:   int Age { get; set; }
   5: }
   6:  
   7: [Test]
   8: public void WithCustomPrefix() {
   9:   var wrapper = factory.GetAdapter<IWithCustomPrefix>(dict);
  10:   wrapper.Name = "Andre";
  11:   wrapper.Age = 26;
  12:  
  13:   Assert.AreEqual("Andre", dict["MyName"]);
  14:   Assert.AreEqual(26, dict["MyAge"]);
  15: }

Custom keys

You can opt for not using a prefix altogether and define the keys manually:

   1: public interface ICustomKeys {
   2:   [DictionaryKey("Foo")]
   3:   string Name { get; set; }
   4:  
   5:   [DictionaryKey("Bar")]
   6:   int Age { get; set; }
   7: }
   8:  
   9: [Test]
  10: public void WithCustomKey() {
  11:   var wrapper = factory.GetAdapter<ICustomKeys>(dict);
  12:   wrapper.Name = "Andre";
  13:   wrapper.Age = 26;
  14:  
  15:   Assert.AreEqual("Andre", dict["Foo"]);
  16:   Assert.AreEqual(26, dict["Bar"]);
  17: }

Convert property to string

In some scenarios you might need all values in the dictionary to be strings. This can be enforced by using the DictionaryStringValuesAttribute:

   1: public interface IPropertyAsString {
   2:   string Name { get; set; }
   3:  
   4:   [DictionaryStringValues]
   5:   int Age { get; set; }
   6: }
   7:  
   8: [Test]
   9: public void ConvertPropertyToString() {
  10:   var wrapper = factory.GetAdapter<IPropertyAsString>(dict);
  11:   wrapper.Name = "Andre";
  12:   wrapper.Age = 26;
  13:  
  14:   Assert.AreEqual("Andre", dict["Name"]);
  15:   Assert.AreEqual("26", dict["Age"]);
  16: }

This attribute can be applied to the interface itself as well to force all properties to be converted to strings.

Collection as string list

If your property implements IEnumerable you can have it converted to a string containing a list of all values:

   1: public interface IAsStringList {
   2:   [DictionaryStringList]
   3:   int[] Values { get; set; }
   4: }
   5:  
   6: [Test]
   7: public void ConvertPropertyToStringList() {
   8:   var wrapper = factory.GetAdapter<IAsStringList>(dict);
   9:   wrapper.Values = new[] {1, 2, 3, 4, 5};
  10:  
  11:   Assert.AreEqual("1,2,3,4,5", dict["Values"]);
  12: }

Several aspects are configurable, like the separator character.

Adapting complex properties

You are not limited to using "flat" interfaces with only simple types. You can also create an adapter that automatically adapts complex properties:

   1: public interface IWithComponent {
   2:   [DictionaryComponent]
   3:   ISimple Simple { get; }
   4: }
   5:  
   6: [Test]
   7: public void CanUseComponent() {
   8:   var wrapper = factory.GetAdapter<IWithComponent>(dict);
   9:   wrapper.Simple.Name = "Andre";
  10:   wrapper.Simple.Age = 26;
  11:   Assert.AreEqual("Andre", dict["Simple_Name"]);
  12:   Assert.AreEqual(26, dict["Simple_Age"]);
  13: }

As you can see IWithComponent.Simple is automatically populated with an adapter itself.

Conclusion

DictionaryAdapter provides means to access the content of a dictionary in an elegant, type safe way. It is a great tool to get rid of strings and to to make your source code robust and refactorable.

Pro

  • Easy to use
  • Very flexible
  • Type safe access even to IDictionary
  • Great tool to improve robustness of code

Cons

  • One time overhead (creating adapters)
  • Memory overhead (in-memory assemblies created by the factory)

Download source code: DictionaryAdapterTests.cs (2.97 kb)

Posted in: Patterns | Snippets | Tools

Tags: , ,