Injecting container into View Models to resolve Enterprise Library's logger? Seems like the wrong approach

Jan 11 at 3:52 PM
Hi,
I have a WPF app that I am building that uses prism with a unity container. For my logging I am using Enterprise Libraries Logging module.

Now, I currently have
  • A WPF project that registers the logger in my bootstrapper
  • Several class library projects that contain individual modules with their views and viewmodels.
  • A class library for my Logger that uses EL logging and contains several types of logging (ie Trace, Info etc)
Now in my Prism module projects I am finding that I have to inject the container to resolve the logger. What bothers me is I am not confident that this is the right approach for doing Enterprise Logging. How to I resolve my logger from my container without constantly injecting my container in every view model. I can provide code if need be.
Thank you
Justine
Editor
Jan 13 at 4:19 AM
You can register the Logger in the container and then allow Prism to inject the logger using constructor injection into the appropriate objects.

Working with Prism, I would create an ILoggerFacade and then return that singleton logger via the CreateLogger() method:
protected virtual ILoggerFacade CreateLogger()
{
    return MyLogger.Instance;
}
The in the Run method of the bootstrapper register the logger:
container.RegisterInstance<ILoggerFacade>(CreateLogger()) // or use protected Logger property;
Then any objects resolved by the container should be injected with the ILoggerFacade instance.

This is basically what the UnityBootstrapper does.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Jan 13 at 1:17 PM
Thanks Randy for your reply. I think the is what I am doing although my Logger is called SGLogger with its accompanying interface ISGLogger so maybe to be clearer I should rename it.

My concern is when working in Prism, when is it appropriate to inject in the container? Ok here is an overview of what I am doing specifically.

My solution has several projects.
  1. WPF project: This is where my bootstrapper is of course.
  2. ContentModule: This is a C# Library project that I inject the container into the constructor to resolve the Logger. So this is what the constructor looks like:
public ContentModuleMain(IUnityContainer container, IRegionManager regionManager) : base(container, regionManager)
    {
        this._container = container;
        this._regionManager = regionManager;
        this._logger = _container.Resolve<ISGLogger>();
    }
Then I have a RegisterTypes method that registers my MainContentViewModel and my MainContentView types.
I also Register my Views with my Region and Resolve my VM's.
Ok, so at the Module level, I have a container dependency. But here is the question.

Here is the constructor for the ViewModel:
public MainContentViewModel(IMainContentView contentView,IUnityContainer container): base(contentView)
    {
        View = contentView;
        _container = container;
        _logger = _container.Resolve<ISGLogger>();


    }
So again, I am passing into the VM the container in order to resolve my logger. I am not confident that this is the right approach just to get to the Logger. Is there another way without having a container dependency?
Note: the Logger has its own C# library and all of the interfaces are placed in a Util C# project for decoupling reasons.

Justine
Editor
Jan 15 at 6:01 AM
Is there a reason why you can't register ISGLogger in the container and then inject ISGLogger directly instead of injecting the container?
    public ContentModuleMain(IRegionManager regionManager, ISGLogger logger) : base(regionManager)
    {
        this._regionManager = regionManager;
        this._logger = logger;
    }
~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Jan 15 at 3:10 PM
That seems perfect, I implemented this but I created a ContentViewModelFactory. So when I create my view model in the Create method of my factory I have
public IContentViewModel Create(ISGLogger _logger)
    {
        return (IContentViewModel) new ContentViewModel( _logger);
    }
So now my question is, does creating a view model in this fashion negate using a container. I thought I needed to resolve
my IContentViewModel instead of using new. But if I Resolve<IContentViewModel> (I registered this in the bootstrapper of my WPF project) then I would need to inject the container again.

Would the above Factory be a correct way to create a View model or do I need to use the container to resolve?

Thank you for your time. I hope this make sense? This is my first project with Prism and I am just getting the feel for using
Prism, containers, and various design patterns.
Editor
Jan 17 at 4:58 AM
I don't think you should have to "new up" any objects; the container should manage object creation and injecting any dependencies. Have you looked at the Prism documentation? The Developer's Guide to Microsoft Prism has a lot of resources that could help (e.g. reference implementation).

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to