Im beginning to learn about dependency injection and have decided to try to build my own (simple) logging facade as an introduction to it. So far I have the logging facade working with the basic functionality of NLog and log4net using Ninject.
(I know that Ninject has its own logging facade, but this is a learning exercise)
However I have run into a problem. What I want to do is to replicate what I log to file in a RichTextBox (Im using winforms). I am able to do this using NLog and log4net directly. The problem I have is that when Ninject wires up the interfaces it creates an implementation of a logger before the richtextbox on my winform has been created and consequently the logger does not find the richtextbox.
What I think I need to do is create the form then get Ninject to create the logger and inject it into the form, but I have no idea how to do this. Although I might be looking at this in completely the wrong way?
Please see below for the code im using to tie this together:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IKernel kernel = new StandardKernel(new DI.NLog.Logger());
var form = kernel.Get<Form1>();
Application.Run(form);
}
}
and the constructor of my form is where the logger is injected.
public Form1(ILog log)
{
InitializeComponent();
_log = log;
}
Any help or advice would be appreciated.
Thank you
Here is one way to think about this:
First, make the form class implement ILog. What this means is that the form it self is a logging destination. When the logging methods are invoked on the form, write what you need to write to the RichTextBox control.
Now, the form itself is an ILog and it also depends on ILog. Also, I assume there is another ILog destination that you would like to log to, e.g., a Log4net adapter.
Here is how I imagine the object graph:
The arrow from X to Y means that X depends on Y, or that Y is injected into X.
The CompositeLog class is a composite ILog, it depends on multiple ILog objects, and when it is invoked to log something, it broadcasts such request to all the ILog dependencies.
As you see from the graph, we have a circular dependency. This can be solved by using Property Injection.
We can use Property Injection inside the CompositeLog class like this:
public class CompositeLog : ILog
{
private ILog[] logs;
public ILog[] Logs
{
set
{
if(logs != null)
throw new Exception("The logs dependencies has been set before");
logs = value;
}
}
public void LogInformation(string message)
{
foreach(var log in logs)
log.LogInformation(message);
}
//Other methods here
//...
}
Notice that this class does not take any dependencies on construction. We later can inject its dependencies via the Logs property.
If you are using Pure DI, your Composition Root would look like this:
var compositeLog = new CompositeLog();
Form1 form = new Form1(compositeLog);
compositeLog.Logs = new ILog[]{ form , new Log4NetAdapter()};
I don't know if this can be done with NInject easily. The bindings are probably going to be complex. In such cases where there are multiple implementations of a single interface, I think that DI containers fail. I suggest you use Pure DI.
Related
In order to try and get a nice logging abstraction with Log4net, I took the abstraction from this SO post and the adapter from this SO post and tried to get them working together.
All that was really left to do was configure the container and that is the part which I have not succeeded in doing.
The config which I have tried is
public static class InfrastructureRegistry
{
public static void RegisterLoggingServices(this Container container)
{
container.RegisterConditional(typeof(ILog), c => LogManager.GetLogger(
c.Consumer.ImplementationType).GetType(),
Lifestyle.Scoped, c => true);
container.RegisterPerWebRequest<ILogger, Log4netAdapter>();
}
}
As you can see from the code, I would like a specific log4net logger which takes its Type from the class into which it is injected. Whilst most logging would be done in a catch-all, I want some logging to happen in lower layers e.g. when a form validation fails.
The ActivationException which I get with that configuration is :
The constructor of type LogImpl contains the parameter with name
'logger' and type ILogger that is not registered. Please ensure
ILogger is registered, or change the constructor of LogImpl.
Not quite sure where to go from here, so any help would be appreciated.
Edit
Sorry, I should point out that I am trying to write it such that I only have to write this config once. The following factory function works, but I don't want to have to manually add more config every time I want to inject a logger:
container.RegisterPerWebRequest<ILog>(() => LogManager.GetLogger(typeof(LoginController)));
The example adapter you point at assumes a single logger for every component in the application, while what you wish is to have a specific logger that 'knows' about its consumer, so it can relate the log messages to the originating class.
Although this seems to be a very common practice when working with tools like log4net and NLog, in my experience, this requirement often comes from the fact that logging is done at too many places in the code. Please read this stackoverflow q/a for more information.
That said, if you want to register the logger conditionally, you will have to change the adapter to a generic class; that way you can make the registration conditional:
public class Log4netAdapter<T> : ILogger
{
private static readonly log4net.ILog logger = LogManager.GetLogger(typeof(T));
public void Log(LogEntry entry)
{
if(entry.LoggingEventType == LoggingEventType.Information)
logger.Info(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Warning)
logger.Warn(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Error)
logger.Error(entry.Message, entry.Exception);
else
logger.Fatal(entry.Message, entry.Exception);
}
}
With this generic class, you can do the following conditional/contextual registration:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Log4netAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
I'm currently working on a WinForms system (I know) where there's a lot of Constructor Injection when creating forms, but if those forms/views need to open another form, I find the DI container has been injected too so that we can locate the implementation of the desired view interface at runtime. e.g.
public partial class MyView : Form, IMyView
{
private readonly IDIContainer _container;
public MyView(IDIContainer container)
{
InitializeComponent();
_container = container;
}
public OpenDialogClick(object sender, EventArgs e)
{
var dialog = container.Resolve<IDialogView>();
dialog.ShowDialog(this);
}
}
I'm aware that this is basically using the container as a service locator. I've been repeatedly told that this is considered an anti-pattern so I'd like to avoid this usage.
I could probably inject the view as part of the constructor like this :
public partial class MyView : Form, IMyView
{
private readonly IDialogView _dialog;
public MyView(IDialogView dialog)
{
InitializeComponent();
_dialog = dialog;
}
public OpenDialogClick(object sender, EventArgs e)
{
dialog.ShowDialog(this);
}
}
But what if the dialog view is quite expensive to instantiate?
It's been suggested that we create some kind of form factory which internally uses the DI container, but to me this seems like simply creating a wrapper around another service locator.
I know that at some point, something has to know how to create an IDialogView, so I'm thinking that either it's resolved when the composite root is created (probably not ideal if there are many forms and some or all are expensive to create), or the composite root itself has a way to resolve the dependency. In which case the composite root has to have a service-locator-like dependency? But then how would child forms create dialogs like this? Would they call up to the composite via, say, events, to open dialogs like this?
One particular problem I keep running up against is that the container is almost impossible to mock easily. This is partly what keeps me thinking about the form factory idea, even though it would just be a wrapper around the container. Is that a sensible reason?
Have I thought myself into a knot? Is there a simple way through this? Or do I just cut the knot and find something that works for me?
Or do I just cut the knot and find something that works for me?
Factory class:
public interface IDialogFactory {
IDialogView CreateNew();
}
// Implementation
sealed class DialogFactory: IDialogFactory {
public IDialogView CreateNew() {
return new DialogImpl();
}
}
// or singleton...
sealed class SingleDialogFactory: IDialogFactory {
private IDialogView dialog;
public IDialogView CreateNew() {
if (dialog == null) {
dialog = new DialogImpl();
}
return dialog;
}
}
Your code:
public partial class MyView : Form, IMyView {
private readonly IDialogFactory factory;
public MyView(IDialogFactory factory) {
InitializeComponent();
//assert(factory != null);
this.factory = factory;
}
public OpenDialogClick(object sender, EventArgs e) {
using (var dialog = this.factory.CreateNew()) {
dialog.ShowDialog(this);
}
}
}
Registration with SimpleInjector
container.RegisterSingle<IDialogFactory, DialogFactory>();
or using singleton version
container.RegisterSingle<IDialogFactory, SingleDialogFactory>();
container.RegisterSingle<IMyView, MyView>();
A local factory, satisfied with an implementation that uses the container and set up in the composition root is not a service locator, it is a dependency resolver.
The difference is as follows: the locator is defined and satisfied somewhere near the definition of the container. In a separate project, to use the locator, you need an external reference to the container infrastructure. This causes the project to rely on external dependency (the locator).
On the other hand, the dependency resolver is local to the project. It is used to satisfy dependencies in its close neighbourhood but it doesn't depend on anything external.
The composition root should not be used to resolve actual specific dependencies such as the one you are concerned about. Instead, the compositon root should set up implementations of all these local dependency resolvers that are used throughout the application. The more local resolver, the better - the MVC's constructor factory is a good example. On the other hand, WebAPI's resolver handles quite few of different services and it is still a good resolver - it is local in the webapi infrastructure, it doesn't depend on anything (rather - other webapi services depend on it) and it can be implemented in any possible way and set up in the Composition Root.
Some time ago I wrote a blog entry about it
http://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html
There you will find your issue discussed and an example of how you set up a factory aka resolver.
You definitely do not want to pass your DI container around your application. Your DI container should only be part of your Composition Root. You could, however, have a factory that uses the DI container within the Composition Root. So if Program.cs is where you are wiring everything up, you could simply define that factory class there.
WinForms was not designed with DI in mind; forms are generated and therefore need default constructors. This may or may not be an issue depending on which DI container you use.
I think in this case, the pain of using constructor injection in WinForms is greater than the pain of any pitfalls you may encounter while using a service locator. There's no shame in declaring a static method in your Composition Root (Program.cs) that wraps a call to your DI container to resolve your references.
I know this problem very well. Everything I learned about solution to this (and I learned A LOT) is more or less camouflaging service locator.
Looking at this answer on SO, I am a bit confused by the following "principle":
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within
your code. Ask for it implicitly by using Constructor Injection.
But what if I have a repository class in my DAL, and I want to supply this instance to an object which is created when a TCP/IP client connects? At what place should I make the injection?
Right now, I have something like:
// gets created when a new TCP/IP client is connected
class Worker
{
private readonly IClient client;
public Worker(IClient client)
{
// get the repository
var repo = IoC.GetInstance<IClientMessagesRepo>();
// create an object which will parse messages
var parser = new MessageParser(client);
// create an object which will save them to repo
var logger = new MessageLogger(parser, repo);
}
}
I obviously cannot create this instance when my app is started. So where do I inject the repo?
Thanks a lot!
You should strive to only call IoC.GetInstance() once.
Since you cannot create the Worker at startup, you should instead create a WorkerFactory and have the DI container inject the dependency into that:
public class WorkerFactory
{
private readonly IClientMessagesRepo clientMessagesRepo;
public WorkerFactory(IClientMessagesRepo clientMessagesRepo)
{
this.clientMessagesRepo = clientMessagesRepo;
}
public Worker Create(IClient client)
{
return new Worker(client, clientMessagesRepo);
}
}
Move IClientMessagesRepo to your constructor arguments:
public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)
Now of course this only moves the problem a bit, to the point where the worker is created. Of course at some point calls into the IoC container are necessary. But in those cases I'd rather pass in the container in a parameter than access it from a static property. Or use some kind of factory.
Have IClientMessagesRepo in your arguments, and let the IoC fill that for you:
public Worker(IClient client, IClientMessagesRepo repo)
{
[...]
}
Obviously, your constructor should do a little more than just create a couple local variables, but you get the idea.
As I understand you have the repository in your IOC container, but not the IClient. Assuming that you have access to the IOC container at the time you create your worker class, and assuming that you are using StructureMap you can write:
IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();
That way you tell StructureMap to use a specific IClient instance, but obtain the other dependencies from the repository.
note: It is some time since I last used StructureMap, so perhaps the code is not 100% correct, but the concept is there, you can provide a concrete dependency when creating a component.
I would like to just markup a property with an attribute [DoInjection] and have unity do the injection. I don't want to have to use prop = Unity.Resolve(type). Thats a pain and messy. Does unity provide attributes to do this or do I have to build my own?
Edit: register in App.Main
ISessionFactory sf = new SessionFactory();
container.RegisterType<IRepository, CustomerRepository>(new InjectionConstructor(sf.CurrentUoW));
container.RegisterInstance<IUnitOfWork>(sf.CurrentUoW);
Using [Dependancy] on IUnitOfWork propery in ClassX other class but it's always null. Do I need to build ClassX instance using Unity to get this to work? It looks like I do have to. I don't like that.
Unity has a DependencyAttribute you can use for this:
public class MyObject
{
private SomeOtherObject _dependentObject;
[Dependency]
public SomeOtherObject DependentObject
{
get { return _dependentObject; }
set { _dependentObject = value; }
}
}
http://msdn.microsoft.com/en-us/library/ff650198.aspx
Based on your question, it sounds like you might be trying to use Unity in the wrong spot and your design sense was telling you it didn't feel right. You should only see Unity where you bootstrap your application. That's your Main method in a console app or Global.asax in a web or wcf app. The idea is to keep relying on dependencies all the way up the chain until you get to where you bootstrap and resolve just that one top level object using your IoC container. In a console app, I do this:
class Program
{
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container
.AddExtension(new ConfigureForConsole(args))
.Resolve<MyApplication>()
.Execute();
}
}
}
http://www.agileatwork.com/console-application-with-ioc/
In this case, MyApplication is my top level object (it doesn't need to be an interface here). The ConfigureForConsole is just a one-off custom container extension that has all the RegisterType lines in there. Alternatively you could initialize the container from App.Config here. The idea though is that your Main method has almost nothing in it. Another benefit of this approach is that it makes your code more portable. I find that console apps usually turn into windows services and keeping things clean here makes that transition pretty painless.
I just started using the Unity Application Block to decouple my classes and make unit testing easier. However, I've run into a problem with circular dependencies.
I have a facade-type class which is a chat bot. It is a singleton class which handles all sort of secondary classes and provides a central place to launch and configure the bot. I also have a class called AccessManager which, well, manages access to bot commands and resources. Boiled down to the essence, I have the classes set up like so:
public class Bot
{
public string Owner { get; private set; }
public string WorkingDirectory { get; private set; }
private IAccessManager AccessManager;
private Bot()
{
// do some setup
// LoadConfig sets the Owner & WorkingDirectory variables
LoadConfig();
// init the access mmanager
AccessManager = new MyAccessManager(this);
}
public static Bot Instance()
{
// singleton code
}
...
}
And the AccessManager class:
public class MyAccessManager : IAccessManager
{
private Bot botReference;
public MyAccesManager(Bot botReference)
{
this.botReference = botReference;
SetOwnerAccess(botReference.Owner);
}
private void LoadConfig()
{
string configPath = Path.Combine(
botReference.WorkingDirectory,
"access.config");
// do stuff to read from config file
}
...
}
I would like to change this design to use the Unity Application Block. I'd like to use Unity to generate the Bot singleton and to load the AccessManager interface in some sort of bootstrapping method that runs before anything else does.
public static void BootStrapSystem()
{
IUnityContainer container = new UnityContainer();
// create new bot instance
Bot newBot = Bot.Instance();
// register bot instance
container.RegisterInstance<Bot>(newBot);
// register access manager
container.RegisterType<IAccessManager,MyAccessManager>(newBot);
}
And when I want to get a reference to the Access Manager inside the Bot constructor I can just do:
IAcessManager accessManager = container.Resolve<IAccessManager>();
And elsewhere in the system to get a reference to the Bot singleton:
// do this
Bot botInstance = container.Resolve<Bot>();
// instead of this
Bot botInstance = Bot.Instance();
The problem is the method BootStrapSystem() is going to blow up. When I create a bot instance it's going to try to resolve IAccessManager but won't be able to because I haven't registered the types yet (that's the next line). But I can't move the registration in front of the Bot creation because as part of the registration I need to pass the Bot as a parameter! Circular dependencies!! Gah!!!
This indicates to me I have a flaw in the way I have this structured. But how do I fix it? Help!!
You can make your life easier by changing the design in the following ways:
Don't implement the Singleton pattern yourself. The DI Container should manage the lifetime of all components, including the Bot class. If you only want a single instance in your application, configure Unity to always return the same instance.
Do everything in your power to remove circular dependencies. You can often do that by changing one of the communication directions to use events instead of direct calls. Another option is to introduce a Mediator.
Notice that none of these recommendations particularly involve Unity. Unity (or any other DI Container) is not a silver bullet that will magically make your code loosely coupled. You must first understand the principles behind DI, and then you can use any DI Container as a tool to help you wire up the dependency graph.
First of all you should let the container manage your singleton lifetime instead of writing the singleton code yourself. To remove your circular dependency, you can remove the Bot from the access manager constructor. Instead, you use an initialize method.
container.RegisterType<Bot>(new ContainerControlledLifecycleManager()); // from my memory...
container.RegisterType<IAccessManager,MyAccessManager>();
var bot = container.Resolve<Bot>();
// Bot.cs
public Bot(IAccessManager manager)
{
manager.InitializeFor(this);
}
For testability reasons you should never call your IOC container from a constructor.