Creating new instances while still using Dependency Injection - c#

A quick description of the environment:
I have a class that represents a chatroom and has a dependency on a logger. It's not the same as a system-wide logger with cross-cutting concerns, but a logger that's tied to that specific chatroom. It logs all activity in that chatroom to it's unique log file. When the chatroom is created I want to open the log file, and when it's destroyed I want to close the log file.
The Problem
Here's the relevant code I'm using.
public interface IChatroomLogger
{
void Log(ServerPacket packet);
void Open();
void Close();
}
public class ChatroomLogger : IChatroomLogger
{
// chatroom name will be used as a file name
public ChatroomLogger(string chatroomName) { ... }
public void Log(ServerPacket packet) { ... }
}
public class Chatroom
{
public Chatroom(string name, IChatroomLogger logger)
{
this.name = name;
this.logger = logger;
this.logger.Open();
}
public IChatromLogger Logger { get { return this.logger; } }
}
public interface IChatManager
{
Chatroom Get(chatroomName);
}
It's used in the application like this:
var room = ChatManager.Get(chatroomName);
romm.DoStuff();
room.Logger.LogPacket(receivedPacket);
The ChatManager is a class which holds references to all chatrooms and is responsible for creating and removing them. I haven't written it yet but that's the interface I've been coding against.
The Question
How do I get ChatManager to create new instances of Chatroom and still use dependency injection??
I'm using Unity to do all my other DI stuff. So far it's worked great. But I'm not sure how to work around this conundrum.
When my concrete implementation of ChatManager creates new chatrooms, it has to pass in an IChatroomLogger. It doesn't know how to construct that...but Unity does. But then I have to pass in IUnityContainer into the ChatManager.
public class ChatManager : IChatManager
{
public ChatManager(IUnityContainer container)
{
this.container = container;
}
public Chat Get(string chatroomName)
{
// get logger from Unity somehow. Not sure how I'd
// pass chatroomName to the concrete instance
var logger = ...
return new Chatroom(chatroomName, logger);
}
}
That just seems wrong for some reason. It seems cleaner to not have the domain know anything about what DI container I'm using.
How could I get new instances of class Chatroom while my application in the middle of running without resorting to some sort of service locator design? Am I overthinking it? Is it not a big deal to pass around Unity? Any thoughts are welcome!

You're right. Using the IUnityContainer like this is no longer using Dependency Injection. Instead it's using the "Service Locator" pattern. What I usually do in cases like this is create an IFactory<T> interface, like this:
public IFactory<T>
{
T Get();
}
Then implement the interface with a class that does know about and use the IUnityContainer. Set up your bindings so that IFactory<> requests will create an instance of this factory class. That way, you can inject the IFactory<Logger> interface into your ChatManager, and call .Get() any time you want a logger instance.

In general, I also think you should avoid passing the container around.
Add a IChatroomProvider to your design with a Create(string roomname) method
In ChatroomProvider, use the container to create named instances (the container will manage the lifecyle of each named instance for you so you don't need to manage a dictionary).
Register the ChatroomProvider with the container
Let ChatManager take a dependency on IChatroomProvider
When ChatManager needs a chatroom it can just ask its IChatroomProvider
Use the container to create the ChatManager instance
Logger instances will be created when chatrooms are created

Related

Dependency Injection for factory with parameters resolved at creation time

Here's what I want to be able to do in my application:
public void BusinessLogic (IFactory workerFactory)
{
string specificObjectType = ... // not known in advance
IWorkerObject workerObject = workerFactory.CreateByType(specificObjectType);
workerObject.DoActualWork();
}
In other words, I want an actual Factory that generates various kinds of IWorkerObject implementations on demand, and I want that Factory to be injectable. And ideally that Factory itself would be able to get those implementation object from the service container too:
public class WorkerFactory
{
public WorkerFactory (IServiceContainer ...)
{ ... }
public IWorker CreateByType (string type)
{
return ...; // a thing that can be provided by the service container
}
}
The reason is that I want to be able to create (for example) a SteelWorker or a CopperWorker or an AluminumWorker depending on what type of metal is represented by that specificObjectType value. This seems like a normal Factory pattern to me, but I don't know how to make a class injectable and give it parameters that aren't resolved until creation time.
If this can be done with Unity, great. If I need to work around it or use another DI framework, that is okay too.
You could inject an IServiceScopeFactory into the IFactory
using (var scope = _serviceScopeFactory.CreateScope())
{
if(criteriaA)
{
return scope.ServiceProvider.GetRequiredService<WorkerA>();
}
}

In the Unity dependency injection framework, is there an equivalent to running BuildUp with InjectionConstructors?

One thing I've always wanted in an DI framework is the ability to use injection constructors with objects that interact with the framework only to consume services. For instance:
public class ServiceClass : IServiceInterface
{
public string Name { get; set; }
}
public class ConsumerClass // explicitly implements no interfaces
{
private readonly IServiceInterface service;
public IServiceInterface Service { get { return service; } }
[InjectionConstructor]
public ConsumerClass(IServiceInterface service)
{
this.service = service;
}
}
static void Main()
{
IUnityContainer container;
// blah blah DI setup stuff
container.RegisterType<IServiceInterface, ServiceClass>();
// Key point here!
container.Instantiate<ConsumerClass>();
// Alternatively:
container.Instantiate(typeof(ConsumerClass));
}
IUnityContainer's BuildUp() method sort of does this, but it requires that you have an instance to pass in, and I can't do this if I want to use injection constructors.
Moreover, I could use:
container.RegisterType(typeof(ConsumerClass),
new InjectionConstructor(container.Resolve<IServiceClass>()));
However, this is a lot of code to be writing--especially for classes that could have several parameters in the constructor--and seems to remove the utility of the container in the first place.
There's also:
container.RegisterType<ConsumerClass, ConsumerClass>();
However with this one, I don't actually want to register the type--I just want it to be created with its dependencies filled via the InjectionConstructor.
So in summary: I want to use injection constructors and I want Unity to do the mapping of registered services for me, and if possible I would like to keep my consumers out of the container. Is there a way to do this that I've missed?
As you have discovered, the .BuildUp method only works on existing instances, to create new instances using Unity you want to use the .Resolve methods, these will create the instance injecting any dependencies as and when required.
For your example use var consumer = container.Resolve<ConsumerClass>() and all of the dependencies will be injected. You do not require any registration for ConsumerClass because it is a concrete type which Unity is able to handle implicitly.

Simple Injector - inject container property

I want to inject Container property via SimpleInjector. I didn't find any functionality of SimpleInjector for that.
Then I wanted to register self container to itself, but Container has no interface.
I want this functionality because I don't to transfer Container object via constructor - because why if I can use auto inject of register objects.
My usage idea:
var container = new Container();
container.Options.AutowirePropertiesWithAttribute<InjectableProperty>();
container.Register<ISomething, Something>(Lifestyle.Singleton);
ISomething:
public interface ISomething
{
void SomeMethod();
}
Something class:
public class Something : ISomething
{
public void SomeMethod()
{
var environment = _container.GetInstance<IEnvironment>();
environment.DoSomething();
}
[InjectableProperty] // - maybe it is not possible (I don't know it)
Container Container {get;set;}
}
Do you have any idea to achieve that?
Thank you very much.
Prevent having your application code depend upon the container. The only place in your application that should know about the existence of your DI library is the Composition Root (the place where you register all your dependencies).
Instead of letting each class call back into the container (which is called the Service Locator anti-pattern), prefer using Dependency Injection. With Dependency Injection you inject dependencies instead of asking for them.
So you can rewrite your class to the following:
public class Something : ISomething
{
private readonly IEnvironment environment;
public Something (IEnvironment environment)
{
this.environment = environment;
}
public void SomeMethod()
{
this.environment.DoSomething();
}
}
Also, prevent doing any logic in your constructors besides storing the incoming dependencies. This allows you to compose object graphs with confidence.
In some cases however, it can still be useful to inject the Container into another class. For instance when creating a factory class that is located inside the Composition Root. In that case you can still use constructor injection, like this:
// Defined in an application layer
public interface IMyFactory
{
IMyService CreateService();
}
// Defined inside the Composition Root
public class MyFactory : IMyFactory
{
private readonly Container container;
public MyFactory(Containter container)
{
this.container = container;
}
public IMyService CreateService(ServiceType type)
{
return type == ServiceType.A
? this.container.GetInstance<MyServiceA>()
: this.container.GetInstance<MyServiceB>();
}
}
If Simple Injector detects a Container constructor argument, it will inject itself into the constructor automatically.

How to use a Provider in Ninject

I have the following code
public class Something {
[Inject]
public Configuration config {get;set;} //singleton
[Inject]
public Provider<WindowHandler> windowsProvider { get; set; } //NOT singleton
public void Search(string text) {
WindowHandler handler = windowsProvider.Create(xxxxxx);
//use the new handler that was created
}
}
but it seems the Provider takes an IContext where I put xxxxxx. Shouldn't the IContext from when I bootstrapped and created Something.cs from the kernel be used. Where is the no parameter Create method on the Provider??? (I am coming from Guice land point of view where it would be coded like above).
so the question is How do I do this correctly?
thanks,
Dean
It seems you are trying to use a provider as a factory in your code.
A provider in Ninject terms is a factory that is given to Ninject to create specially created objects. Therefore it gets the resolving context which can be used to create different instances depending where the instance in injected into.
public class FooProvider : Provider<IFoo>
{
public override IFoo CreateInstance(IContext ctx)
{
// add here your special IFoo creation code
return new Foo();
}
}
kernel.Bind<IFoo>().ToProvider<FooProvider>();
What you want is a factory in your coder that creates an instance of WindowHandler. Therefore create an interface to create the instance like this:
public interface IWindowHandlerFactory
{
WindowHandler Create();
}
Bind<IWindowHandlerFactory>().ToFactory();
Alternatively you can inject Func<WindowHandler> without adding a configuration. But this is less meaningful in my opinion.
NOTE: All this requires Ninject.Extensions.Factory available as prerelease 3.0.0-rc2 from Nuget.
See also: http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/
Well, my final solution was to cheat in ninject 2.0 with the following code...
var windowFactory = kernel.Get<IEWindowFactory>();
var tabFactory = kernel.Get<IETabFactory>();
windowFactory.Kernel = kernel;
tabFactory.Kernel = kernel;
and in the bindings list I have
Bind<IEWindowFactory>().ToSelf().InSingletonScope();
Bind<IETabFactory>().ToSelf().InSingletonScope();
and after that I just start my app
var main = kernel.Get<MainForm>();
main.Start();
and of course the factories are injected where I need them in the heirarchy of that MainForm.
so I manually put the kernel when starting up and then when I bootstrap my app, naturally these factories are fields in classes with [Ninject] annotation and so they can create objects. not the cleanest until we get 3.0, but it works(and I hate the extra factory classes I have to write code for but oh well).

With Unity how do I inject a named dependency into a constructor?

I have the IRespository registered twice (with names) in the following code:
// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));
// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));
IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();
But then when I want to resolve this (to use the IRepository) I have to do a manual resolve like this:
public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);
.....
}
What I would like to do is to have it resolved in the constructor (just like IUnityContainer). I need some way to say which named type to resolve to.
Something like this: (NOTE: Not real code)
public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Is there a way to make my fake code work?
You can configure dependencies with or without names in the API, attributes, or via the config file. You didn't mention XML above, so I'll assume you're using the API.
To tell the container to resolve a named dependency, you'll need to use an InjectionParameter object. For your ClientModel example, do this:
container.RegisterType<IClientModel, ClientModel>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
)
);
This tells the container "When resolving ClientModel, call the constructor that takes a single IRepository parameter. When resolving that parameter, resolve with the name 'Client' in addition to the type."
If you wanted to use attributes, your example almost works, you just need to change the attribute name:
public ClientModel([Dependency("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
This is a very late response but the question still shows up in Google.
So anyways, 5 years later...
I have a pretty simple approach. Usually when you need to use "named dependency" it's because you're trying to implement some kind of strategy pattern. In that case, I simply create a level of indirection between Unity and the rest of my code called the StrategyResolver to not be directly depending on Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Usage:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Registration:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Now, the nice thing about this is that I will never have to touch the StrategyResolver ever again when adding new strategies in the future.
It's very simple. Very clean and I kept the dependency on Unity to a strict minimum. The only time I would have touch the StrategyResolver is if I decide to change container technology which is very unlikely to happen.
Hope this helps!
Edit: I don't really like the accepted answer because when you use the Dependency attribute in your service's constructor you actually have a hard dependency on Unity. The Dependency attribute is part of the Unity library. At that point you might as well pass an IUnityContainer dependency everywhere.
I prefer having my service classes depend on objects that I completely own instead of having a hard dependency on an external library all over the place. Also using Dependency attribute makes the constructors signatures less clean and simple.
Furthermore, this technique allows to resolve named dependencies at runtime without having to hardcode the named dependencies in the constructor, in the application configuration file or use InjectionParameter which are all methods that require to know what named dependency to use at design time.
Edit (2016-09-19):
For those that might wonder, the container will know to pass itself when you are requesting IUnityContainer as dependency, as shown in the StrategyResolver constructor signature.
Edit (2018-10-20):
Here's another way, simply using a factory:
public class SomeStrategyFactory : ISomeStrategyFactory
{
private IStrategy _stratA;
private IStrategy _stratB;
public SomeFactory(IStrategyA stratA, IStrategyB stratB)
{
_stratA = stratA;
_stratB = stratB;
}
public IStrategy GetStrategy(string namedStrategy){
if (namedStrategy == "A") return _stratA;
if (namedStrategy == "B") return _stratB;
}
}
public interface IStrategy {
void Execute();
}
public interface IStrategyA : IStrategy {}
public interface IStrategyB : IStrategy {}
public class StrategyA : IStrategyA {
public void Execute(){}
}
public class StrategyB : IStrategyB {
public void Execute() {}
}
Usage:
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
Registration:
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
This 2nd suggestion is the same thing but using the factory design pattern.
Hope this helps!
You should be able to use ParameterOverrides
var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );
edit:
I'm not sure why you're passing around the UnityContainer - personally, we inject our dependencies into the constructor themselves (which is "normal" from what I've seen). But regardless, you can specify a name in your RegisterType and Resolve methods.
IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");
and it will give you the type you registered for that name.
Don't do this - just create a class ClientRepository : GenericRepository { } and utilise the Type system.

Categories

Resources