Giacomo Tagliabue
Giacomo Tagliabue

Reputation: 1759

Ninject to load different implementations

I have a web service (let's call it WebSite) that uses an Interface (IDataService). the webservice project implements a "fake" service with hardcoded objects (DesignDataService) that I use to develop the websit while I wait for my colleagues to build the real implementation (BreadDataService).

My NinjectWebCommon is currently like this:

private static void RegisterServices(IKernel kernel)
{
  kernel.Bind<IDataService>().To<DesignDataService>();
}

What I want is to be able to provide my colleague a way to test the BreadDataService on my WebService, while I can go on using DesignDataService. I can't use the BreadDataService on my machine because it requires some assemblies that I don't have (+ the database).

So, what is the approach here? The current dependency tree is like that:

I don't want to reference the BreadDataService project inside the WebSite Project, I was maybe thinking about a folder in WebSite where they can put the BreadDataService dll and ninject takes it depending on some configuration in web.config.

Hints?

Upvotes: 0

Views: 643

Answers (2)

Giacomo Tagliabue
Giacomo Tagliabue

Reputation: 1759

I used qujck approach to build these extension methods. The main difference is that it relies on Ninject.Extensions.Conventions' FromAssembliesInPath method

Upvotes: 1

qujck
qujck

Reputation: 14580

Something like this will do the trick

  • load external assemblies
  • search for an implementation
  • default to your design time version if none are found

Here's the basic code

IEnumerable<Assembly> assemblies = this.LoadAssemblies(@"C:\Temp");
Type implementation = FindImplementation(assemblies, typeof(IDataService));

IKernel kernel = new StandardKernel();

kernel.Bind<IDataService>().To(implementation ?? typeof(DesignDataService));

This method will load external assemblies (such as plugins) from a specific folder

private IEnumerable<Assembly> LoadAssemblies(string folder)
{
    IEnumerable<string> dlls =
        from file in new DirectoryInfo(folder).GetFiles()
        where file.Extension == ".dll"
        select file.FullName;

    IList<Assembly> assemblies = new List<Assembly>();

    foreach (string dll in dlls)
    {
        try
        {
            assemblies.Add(Assembly.LoadFile(dll));
        }
        catch
        {
        }
    }

    return assemblies;
}

And this method will search a set of assemblies for an implementation. Please note that I have specifically used SingleOrDefault() so that this will fail if there is more than one implementation.

private Type FindImplementation(
    IEnumerable<Assembly> assemblies, 
    Type serviceType)
{
    var implementationType = (
        from dll in assemblies
        from type in dll.GetExportedTypes()
        where serviceType.IsAssignableFrom(type)
        where !type.IsAbstract
        where !type.IsGenericTypeDefinition
        select type)
        .SingleOrDefault();

    return implementationType;
}

Upvotes: 2

Related Questions