Schlagwort-Archive: IoC

Castle Windsor – Handy Ruse Part III

In this blog entry I published code for an IoC Initializer. The following container Integration Test tries to create an instance of each registered service that is not of type IAmNotTestable. Definitely an Integration Tests that every application needs!

Integration Test of the container using Machine.Specifications as UnitTesting Framework:

   1: using System;

   2: using System.Diagnostics;

   3: using System.Linq;

   4: using Castle.MicroKernel;

   5: using Castle.Windsor;

   6: using comWORK.Contracts;

   7: using comWORK.Infrastructure.IoC;

   8: using Machine.Specifications;

   9: using Machine.Specifications.Utility;

  10:  

  11: namespace UAR.IntegrationTests

  12: {

  13:     public abstract class ContainerSpecs

  14:     {

  15:         protected static IWindsorContainer CreateContainer()

  16:         {

  17:             return new IoCInitializer()

  18:                     .RegisterComponents()

  19:                     .Container;

  20:         }

  21:     }

  22:  

  23:     [Subject("Container Specs")]

  24:     public class When_the_application_starts_up : ContainerSpecs

  25:     {

  26:         static IHandler[] _handlers;

  27:         static IWindsorContainer _container;

  28:  

  29:         Establish context = () => { _container = CreateContainer(); };

  30:  

  31:         Because of = () => { _handlers = _container.Kernel.GetAssignableHandlers(typeof(object)); };

  32:  

  33:         Cleanup after = () => _container.Dispose();

  34:  

  35:         It should_be_able_to_create_an_instance_of_each_registered_service =

  36:             () => _handlers

  37:                       .Where(

  38:                           handler =>

  39:                           handler.ComponentModel.Implementation.GetInterfaces().Contains(typeof(IAmNotTestable)) == false)

  40:                       .Each(handler => handler.ComponentModel.Services

  41:                                            .Each(service =>

  42:                                            {

  43:                                                Debug.WriteLine(String.Format("{0}: {1}/{2}",

  44:                                                                              handler.ComponentModel.Name,

  45:                                                                              service.Name,

  46:                                                                              handler.ComponentModel.Implementation.Name));

  47:  

  48:                                                if (service.ContainsGenericParameters)

  49:                                                {

  50:                                                    service.GetGenericArguments()

  51:                                                        .Each(argument => argument.GetGenericParameterConstraints()

  52:                                                                              .Each(

  53:                                                                                  constraint =>

  54:                                                                                  _container.Resolve(service.MakeGenericType(constraint))));

  55:                                                }

  56:                                                else

  57:                                                {

  58:                                                    _container.Resolve(service);

  59:                                                }

  60:                                            }));

  61:     }

  62: }

Implementation of IAmNotTestable

   1: public interface IAmNotTestable{}

Notice: I will publish a new version soon that addresses some open problems that i don’t want to mention here.

Advertisements

Castle Windsor – Handy Ruse Part II

In every application you have to initialize the container as part of the bootstrapping process. I moved the bootstrapping logic into a seperate assembly. Here’s the IoC part as fluent API. The code registers all implementations of IWindsorInstaller contained in the folder of the executing assembly. I also have a method “RunStartupConfiguration” that executes the start-method of all components which implement the interface. This could be useful for configuration reason for example.

Implementation of IoCInitializer

   1: public class IoCInitializer : IDisposable

   2: {

   3:     public IWindsorContainer Container { get; private set; }

   4:  

   5:     public IoCInitializer()

   6:     {

   7:         Container = new WindsorContainer();

   8:     }

   9:  

  10:     public void Dispose()

  11:     {

  12:         if (Container != null)

  13:         {

  14:             Container.Dispose();

  15:             Container = null;

  16:         }

  17:     }

  18:  

  19:     public IoCInitializer RegisterComponents()

  20:     {

  21:         var appDomainDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

  22:         var foundAssemblies = FromAssembly.InDirectory(new AssemblyFilter(appDomainDirectory));

  23:  

  24:         Container.Install(foundAssemblies);

  25:  

  26:         return this;

  27:     }

  28:  

  29:     public IoCInitializer RunStartupConfiguration()

  30:     {

  31:         Container

  32:             .ResolveAll<IStartupTask>()

  33:             .ToList()

  34:             .ForEach(x => x.Start());

  35:         return this;

  36:     }

  37: }

 

Implementation of IStartupTask:

   1: public interface IStartupTask

   2: {

   3:     void Start();

   4: }

 

You can call this in your bootstrapping logic this way:

   1: Container = new IoC.IoCInitializer()

   2:     .RegisterComponents()

   3:     .RunStartupConfiguration()

   4:     .Container;

 

Be careful, the container and class modifiers are public! Instead you should make it internal and integrate it into the assembly that is responsible for bootstrapping.

Castle Windsor – Handy Ruse Part I

Today I want to share some implementations that I use every once in a while:

Scenario 1: You have an assembly that contains all WinForm controls or perhaps ViewModel classes instead. You don’t want to adapt your installer again and again, if you create new controls respectively new ViewModels.

The following snippet shows an Installer that registers all ViewModels in a WPF assembly of mine. Of course I need to decorate my ViewModels with an special interface, in this case IAmViewModel:

   1: public class Installer : IWindsorInstaller

   2: {

   3:     public void Install(IWindsorContainer container, IConfigurationStore store)

   4:     {

   5:         container.Register(Components().ToArray());

   6:     }

   7:  

   8:     private static IEnumerable<IRegistration> Components()

   9:     {

  10:         yield return Classes.FromThisAssembly()

  11:             .BasedOn<IAmViewModel>()

  12:             .WithServiceSelf()

  13:             .LifestyleTransient();

  14:     }

  15: }

You can afford the same for WinForms. You don’t even have to create an interface:

   1: private static IEnumerable<IRegistration> Components()

   2: {

   3:     yield return Classes.FromThisAssembly()

   4:         .BasedOn<Form>()

   5:         .WithServiceSelf()

   6:         .LifestyleTransient();

   7: }

 

In some little (!) cases it can be useful to inject the container itself into an object. For that reason you can register the container in itself:

   1: Container.Register(

   2:     Component.For<IWindsorContainer>().Instance(Container)

   3: );

ReSharper & IoC Container

Wer in seiner Architektur auf IoC Container einsetzt, der bekommt bei ReSharper immer die Meldung “Possible NullReferenceException”, wenn er z.B. im Konstruktor den NULL-check unterlässt. Allerdings ist diese Prüfung meiner Meinung nach unnötig, da der Container ja entweder eine Instanz erzeugen kann oder ggf. eine Exception schmeißt. Deshalb würde ich diese Prüfung in ReSharper abschalten:

Geht dazu in eure ReSharper Optionen (Achtung: Ab Version 6.1 gibt es ja unterschiedliche Layer an Optionen. Achtet darauf, dass ihr im richtigen Layer seid!). Danach findet ihr unter Code Inspection – Inspection Severity im Tab All, wenn ihr beim Filter “null” eingebt unter der Kategorie “Potential Code Quality Issues” die Option “Possible System.NullReferenceException”, welche ihr auf “Do not show” stellen müsst.

image

Using an IoC-Container right

I noticed that some people don’t use their IoC-Container in the manner they should to. They inject the container into their objects like this:

   1: public class Foo : IFoo

   2: {

   3:     private IContainer _container;

   4:  

   5:     public Foo(IContainer container) {

   6:         _container = container;

   7:     }

   8:  

   9:     public Boo GetBooForFoo(int id) {

  10:         var boo = _container.Resolve<IMyService>().GetBooById(id);

  11:         return boo;

  12:     }

  13: }

A friend of mine (Web Developer) uses the same approach (not with an IoC but an array) in PHP: He injects an array that contains every dependency. When i asked him why he is doing this that way, he told me that he doesn’t want his API to change when he needs more dependencies.

So why is this a bad decision:

  • Fail Fast Principle: If the requested service IMyService in line 10 is not found, it will raise an Exception (for example an ComponentNotFoundException). In this scenario that’s no fracture of the leg but what if you would have executed some important changes before? You shouldn’t be able call a method without having the a valid starting point. It’s much better and cleaner to get an exception when you instantiating the object Foo.
  • Keep in mind why you are using an container: You want to implement the Inversion of Control principle. It’s not your call that should be in control, it’s your container. It’s paradox to use an IoC-Container when you develop your code to annul the basic principle behind. Another point is that you have a hard coded dependency to a specific container implementation so you’re not able to switch you IoC-Container.
  • And my last consideration is about the benefit that you’re api won’t change: Don’t hide dependencies! If you’re not the only developer that works with that code, you will get big problems because you change the components behaviour without getting errors. A developer that uses this component is wondering why his program is not working correctly any longer. Or – and that would be really upsetting – the calling component works in some cases and in some cases not for example if line 10 would be in a switch statement.

Too make a long story short: Here’s my approach

   1: public class Foo : IFoo

   2: {

   3:     private IMyService _myService;

   4:     

   5:     public Foo(IMyService myService) {

   6:         //you might want to do a null check

   7:         //what's not necessary if you unit tested your IoC right

   8:         _myService = myService

   9:     }

  10:  

  11:     //you should know what to do now

  12: }

Inversion of Control and Entity Framework

Today i want to show you my approach to resolve the requested entity framework object context at runtime. Starting point:

  • First, i want to have just one implementation of an IUnitOfWork to resolve any kind of repository like Repository<Order>
  • Second, my unit of work should autodiscover the proper context for my requested type of domain model as i have different databases and object contexts. For example, Order is a domain object of my domain model (namespace Domain.ComWork) according to the context ‘comwork’, which is mapping to the database ‘comwork’. There’s another domain object like Customer in my domain model (namespace Domain.MyHeco) according to the context ‘myheco’, which is mapping to the database ‘myheco’.

So how can i achieve this? I will use an IoC container like Castle.Windsor. You can add it to your Visual Studio project by the nuget command “install-package Castle.Windsor”. I want to mention that this scenario needs a little bit of advanced IoC techniques because the dependent component has to be resolved at runtime. So you’re not able to register a dedicated component for an interface. Instead you’ve got to use a facility. Allright, so we tell the container that we will register a facility:

   1: container.AddFacility<TypedFactoryFacility>();

 

In line 1 we tell the container that it has to load the necessary infrastructure for facilities. Let’s take a look at the registration process. Here’s my method that will return me an IEnumerable of IRegistration.

   1: static IEnumerable<IRegistration> Components()

   2: {

   3:     yield return Component

   4:         .For<IContextFactory>()

   5:         .AsFactory(c => c.SelectedWith<ContextFactoryHandlerSelector>());

   6:     yield return Component

   7:         .For<ContextFactoryHandlerSelector>();

   8:     yield return Component

   9:         .For<IUnitOfWork>()

  10:         .ImplementedBy<UnitOfWork>();

  11:     yield return Component

  12:       .For<ComWorkContext>()

  13:       .Named("comworkcontext");

  14:     yield return Component

  15:       .For<MyHecoContext>()

  16:       .Named("myhecocontext");

  17: }

 

Here’s the good news: Castle Windsor has an out of the box feature that creates you the needed factory. In other words: The container creates automatically the factory. You’re code is unaware of the container. Take a look at this article. If you want to use this you’ve have to follow some conventions. In my approach i decided to develop my own implementation to follow my own convetions. Take a look at line 5.  With “.AsFactory” i tell the container that i don’t register a concrete implementation for that service (IContextFactory). If i would follow the conventions of Castle.Windsor calling AsFactory() would be enough.

Here’s the code for my own implementation of a TypedFactoryComponentSelector (this would be auto generated by using just AsFactory without parameters):

   1: public class ContextFactoryHandlerSelector : ITypedFactoryComponentSelector

   2: {

   3:     public TypedFactoryComponent SelectComponent(MethodInfo method, 

   4:         Type type, object[] arguments)

   5:     {

   6:         var requestFor = method.GetGenericArguments().First();

   7:         

   8:         var @namespace = string.Format("{0}context", 

   9:             requestFor.Namespace.ToLower()

  10:             .Replace("domain.",""));

  11:         

  12:         return new TypedFactoryComponent(@namespace, method.ReturnType, null);

  13:     }

  14: }

 

My convention is pretty simple: The name of my object context is the same as the namespace of my model without the string “domain.” and with “context” appended.

Sample: Full name of my domain object: “domain.comwork.order”

  • use just the namespace –> domain.comwork
  • replace domain –> comwork
  • add context –> comworkcontext

I have two kind of domain models (domain.comwork and domain.myheco) so i need two contexts (comworkcontext and myhecocontext). Every context is registered:

   1: yield return Component

   2:   .For<ComWorkContext>()

   3:   .Named("comworkcontext");

   4: yield return Component

   5:   .For<MyHecoContext>()

   6:   .Named("myhecocontext");

 

Now we’ve got it: We have a facility that invokes a call to my self implemented factory if a service (defined in the interface IContextFactory) is requested. The factory returns the name of the needed context at runtime. My Interface looks like this:

   1: public interface IContextFactory

   2: {

   3:     ObjectContext GetContextFor<T>();

   4: }

And here’s the generic part. If i call GetContextFor<domain.comwork.order> i will get my comworkcontext. If i call GetContextFor<domain.myheco.customer> i will get my myhecocontext.

The last step is to inject the factory in my UnitOfWork. Nothing easier than that:

   1: public class UnitOfWork : IUnitOfWork

   2: {

   3:     private readonly IContextFactory _factory;

   4:  

   5:     public UnitOfWork(IContextFactory factory)

   6:     {

   7:         _factory = factory;

   8:     }

   9:  

  10:     //here you would return an IRepository<T>

  11:     //this is just a sample code

  12:     public void GetRepository<T>() where T : class 

  13:     {

  14:         Console.WriteLine(_factory.GetContextFor<T>().GetContextName());

  15:     }

  16: }

 

And how can i resolve my concrete UnitOfWork in my program?

   1: static class Program

   2: {

   3:     static void Main(string[] args)

   4:     {

   5:             using (var container = new WindsorContainer())

   6:             {

   7:                 container.AddFacility<TypedFactoryFacility>();

   8:                 container.Register(Components().ToArray());

   9:  

10: container.Resolve<IUnitOfWork>()

.GetRepository<Domain.ComWork.Foo>();

11: container.Resolve<IUnitOfWork>()

.GetRepository<Domain.MyHeco.Bar>();

  12:             }

  13:     }

  14:  

  15:     static IEnumerable<IRegistration> Components()

  16:     {

  17:         //Registrations...

  18:     }

  19: }

%d Bloggern gefällt das: