Created
January 16, 2013 18:48
-
-
Save jamesmanning/4549670 to your computer and use it in GitHub Desktop.
example of how *not* to do namespace-based factory binding with ninject
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Ninject; | |
using Ninject.Extensions.Factory; | |
namespace SomeRootNamespace | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var kernel = new StandardKernel(); | |
// make sure all the necessary bindings for the implementation classes are registered | |
kernel.Bind<IFoo>().To<Gen1.Foo>(); | |
kernel.Bind<IFoo>().To<Gen2.Foo>(); | |
kernel.Rebind<IFooFactory>().To<FooFactoryManual>(); | |
TestFooFactory(kernel); | |
kernel.Rebind<IFooFactory>().ToFactory(() => new NamespaceBasedProvider(kernel)); | |
TestFooFactory(kernel); | |
} | |
private static void TestFooFactory(StandardKernel kernel) | |
{ | |
var factory = kernel.Get<IFooFactory>(); | |
factory.CreateFoo("Gen1").DoStuff(); | |
factory.CreateFoo("Gen2").DoStuff(); | |
try | |
{ | |
factory.CreateFoo("Gen3").DoStuff(); | |
throw new InvalidOperationException("Gen3 attempt should have failed"); | |
} | |
catch (Exception) | |
{ | |
Console.WriteLine("Gen3 correctly failed"); | |
} | |
} | |
} | |
public interface IFoo | |
{ | |
void DoStuff(); | |
} | |
public interface IFooFactory | |
{ | |
IFoo CreateFoo(string gen); | |
} | |
public class FooFactoryManual : IFooFactory | |
{ | |
public IFoo CreateFoo(string gen) | |
{ | |
switch (gen) | |
{ | |
case "Gen1": | |
return new Gen1.Foo(); | |
case "Gen2": | |
return new Gen2.Foo(); | |
default: | |
throw new InvalidOperationException("Unsupported gen value: " + gen); | |
} | |
} | |
} | |
public class NamespaceBasedProvider : StandardInstanceProvider | |
{ | |
private readonly IKernel _kernel; | |
public NamespaceBasedProvider(IKernel kernel) | |
{ | |
_kernel = kernel; | |
} | |
public override object GetInstance(Ninject.Extensions.Factory.Factory.IInstanceResolver instanceResolver, System.Reflection.MethodInfo methodInfo, object[] arguments) | |
{ | |
var implementationNamespaceToUse = arguments.Single().ToString(); | |
// EVIL - DO NOT USE THIS - IT INSTANTIATES ALL POSSIBLE INSTANCES UNNECESSARILY | |
var allInstances = _kernel.GetAll(methodInfo.ReturnType); | |
var instanceToUse = allInstances.FirstOrDefault(x => x.GetType().Namespace.EndsWith(implementationNamespaceToUse)); | |
return instanceToUse; | |
} | |
} | |
} | |
namespace SomeRootNamespace.Gen1 | |
{ | |
public class Foo : IFoo | |
{ | |
public void DoStuff() | |
{ | |
Console.WriteLine("Doing Type1 stuff"); | |
} | |
} | |
} | |
namespace SomeRootNamespace.Gen2 | |
{ | |
public class Foo : IFoo | |
{ | |
public void DoStuff() | |
{ | |
Console.WriteLine("Doing Type2 stuff"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment