Multiple navigation control through dependency injection - c#

My base content class. I used this class as a theme for my project. I do not know this info relevant or not. In here I create an abstract method that would overload the navigation method.
public abstract class BaseContentPage : ContentPage
{
public readonly BaseViewModel BaseViewModel;
public BaseContentPage(BaseViewModel baseViewModel)
{
BaseViewModel = baseViewModel;
}
public abstract void Navigate(SelectedItemChangedEventArgs e);
}
In my locator where I build the dependency Injection public class Locator. in this class mainly focus on adding this class to the container to make the all code loss coupling
private readonly ContainerBuilder _builder;
public Locator()
{
_builder = new ContainerBuilder();
RegisterTypes();
Container = _builder.Build();
}
public IContainer Container { get; set; }
private void RegisterTypes()
{
_builder.RegisterType<WardListService>().As<IWardListService>();
_builder.RegisterType<WardListPageViewModel>();
_builder.RegisterType<WardListPage>();
_builder.RegisterType<PatientService>().As<IPatientService>();
_builder.RegisterType<PatientListPageViewModel>();
_builder.RegisterType<PatientListViewPage>();
_builder.RegisterType<PatientDetailsPageViewModel>();
_builder.RegisterType<PatientDetailsViewPage>(); }
In my app.Xaml.Cs file
public App()
{
InitializeComponent();
Locator locator = new Locator();
Container = locator.Container;
MainPage = new NavigationPage(Container.Resolve<WardListPage>());
}
public static IContainer Container;
I used this method for navigation in my view code behind page
public async override void Navigate(SelectedItemChangedEventArgs e)
{
PatientDetailsViewPage patientDetailsViewPage = App.Container.Resolve<PatientDetailsViewPage>();
patientDetailsViewPage.BaseViewModel.SelectedPatient = e.SelectedItem as PatientViewModel;
await Navigation.PushAsync(patientDetailsViewPage);
}
This code is working perfectly but this only can navigate to one page.meaning as an example on one page we have two buttons that navigate to two different pages. I don't know how to implement this task using above navigate overloader. How to do it can anyone give suggestion to overcome the problem?. Also, I used autofac for dependency injection Thank you

You can define container in your CustomNavigationPage and use in every navigation page instance.
public class CustomNavigationPage : NavigationPage
{
public static IContainer Container;
public CustomNavigationPage()
{
Locator locator = new Locator();
locator.RegisterTypes();
Container = locator.Container();
}
}
It is dummy code what i mentioned.
You creating a navigation page that customized. So you can use this navigating your pages for example:
CustomNavigationPage.PushASync(new TestPage(Container.Resolve<WardListPage>())):
If use this your custom navigation page will be resolve your dependencies every call.
To improve performance you can register your dependencies with
singleton pattern. When the app started, dependencies will be registered.
After you use this registered dependencies.
There is an improvement : You define a static locator with singleton pattern it registers dependencies in app.cs
public sealed class Locator
{
private static Locator locator = null;
private static readonly object padlock = new object();
Locator()
{
//your registries
}
public static Locator Locator
{
get
{
lock (padlock)
{
if (locator == null)
{
locator = new Locator();
}
return locator;
}
}
}
}
And your app.cs :
public App()
{
InitializeComponent();
Locator locator = new Locator();
Container = locator.Container;
.
.
}
public static IContainer Container;
This way you only one time register your dependencies. There is no duplication of code. Only one instance will be used.

Related

Unity Config error in console application

Hi am working on console application which uses Dependency Injection pattern, i have created the interface like
public interface IRecurringTransactionPlanDataService : IService<RecurringTransactionPlan>
{
IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData();
}
and the class implements as
public class RecurringTransactionPlanDataService : Service<RecurringTransactionPlan>, IRecurringTransactionPlanDataService
{
private readonly IRepositoryAsync<RecurringTransactionPlan> _repository;
public RecurringTransactionPlanDataService(IRepositoryAsync<RecurringTransactionPlan> repository)
: base(repository)
{
_repository = repository;
}
public IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData()
{
return _repository.RecurringTransactionPlanData();
}
}
The repository:
public static class RecurringTransactionPlanRepository
{
public static IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData(this IRepository<RecurringTransactionPlan> repository)
{
return repository.Queryable();
}
}
the above code all in separate projects, i am using this in MVC and also in console application, while using in MVC there is no error fetching data from db by UnityConfig.cs, but in console application we need to manually register and resolve the interfaces, i have tried this,
My Console Application:
public class RecurringTransaction
{
public readonly IRecurringTransactionPlanDataService _recurringTransactionPlanDataService;
public RecurringTransaction()
{
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
}
}
public class Program
{
public static void Main(string[] args)
{
FeePaymentTracker.UnityConfig.RegisterComponents();
RecurringTransaction rt = new RecurringTransaction();
var restult = rt.GetRecurringTransactionRecords();
}
}
am getting the above error. expecting your ideas to resolve the error.
In your RecurringTransaction-method you create a new container and then you register RecurringTransactionPlanDataService in that new container. But you do not register the dependencies that the implementation RecurringTransactionPlanDataService has. That container will only have one registration.
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Since RecurringTransactionPlanDataService has a dependency to IRepositoryAsync<RecurringTransactionPlan> you need to register that as well.
Change your code to:
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
container.RegisterType<IRepositoryAsync<RecurringTransactionPlan>, YourRepositoryImplementation>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
As a sidenote you may want to re-use the same container. In console-applications I usually resolve a "ProgramStarter", which then gets the correct injections. This way you only need to use the service locator anti-pattern in the root. But can use proper DI in the rest of the application.
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>();
// Pass the same container to the config.
FeePaymentTracker.UnityConfig.RegisterComponents(container);
var program = container.Resolve<ProgramStarter>();
program.Run();
}
}
public class ProgramStarter
{
IRecurringTransactionPlanDataService _dataService;
public ProgramStarter(IRecurringTransactionPlanDataService dataService)
{
_dataService = dataService;
}
public void Run()
{
// Do stuff.
}
}
in the code that you have posted you have an interface called IPaymentService and its implementation. It seems ok. But then in the screenshot you are trying to resolve a dependency called RecurringTransactionPlanDataService. Make your that you have registered this dependency. Could you add information about how you are registering the dependencies in the container?
The problem in your code is that you are trying to resolve the implementation instead of the interface. You should change the following line:
_recurringTransactionPlanDataService = container.Resolve<RecurringTransactionPlanDataService>();
with that:
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Cheers,

Dependency injection using Azure WebJobs SDK?

The problem is that the Azure WebJobs SDK supports only public static methods as job entry-points which means there is no way of implementing constructor/property injection.
I am unable to find anything about this topic in official WebJobs SDK documentation/resources. The only solution that I came across is based on service locator (anti) pattern described on this post here.
Is there a good way to use "proper" dependency injection for projects based on Azure WebJobs SDK?
Azure WebJobs SDK now supports instance methods. Combining this with a custom IJobActivator allows you to use DI.
First, create the custom IJobActivator that can resolve a job type using your favourite DI container:
public class MyActivator : IJobActivator
{
private readonly IUnityContainer _container;
public MyActivator(IUnityContainer container)
{
_container = container;
}
public T CreateInstance<T>()
{
return _container.Resolve<T>();
}
}
You need to register this class using a custom JobHostConfiguration:
var config = new JobHostConfiguration
{
JobActivator = new MyActivator(myContainer)
};
var host = new JobHost(config);
Then, you can use a simple class with instance methods for your jobs (here I'm using Unity's constructor injection feature):
public class MyFunctions
{
private readonly ISomeDependency _dependency;
public MyFunctions(ISomeDependency dependency)
{
_dependency = dependency;
}
public Task DoStuffAsync([QueueTrigger("queue")] string message)
{
Console.WriteLine("Injected dependency: {0}", _dependency);
return Task.FromResult(true);
}
}
This is how I handled scoping using the new SDK. Using the IJobactivator as described by Alexander Molenkamp.
public class ScopedMessagingProvider : MessagingProvider
{
private readonly ServiceBusConfiguration _config;
private readonly Container _container;
public ScopedMessagingProvider(ServiceBusConfiguration config, Container container)
: base(config)
{
_config = config;
_container = container;
}
public override MessageProcessor CreateMessageProcessor(string entityPath)
{
return new CustomMessageProcessor(_config.MessageOptions, _container);
}
private class CustomMessageProcessor : MessageProcessor
{
private readonly Container _container;
public CustomMessageProcessor(OnMessageOptions messageOptions, Container container)
: base(messageOptions)
{
_container = container;
}
public override Task<bool> BeginProcessingMessageAsync(BrokeredMessage message, CancellationToken cancellationToken)
{
_container.BeginExecutionContextScope();
return base.BeginProcessingMessageAsync(message, cancellationToken);
}
public override Task CompleteProcessingMessageAsync(BrokeredMessage message, FunctionResult result, CancellationToken cancellationToken)
{
var scope = _container.GetCurrentExecutionContextScope();
if (scope != null)
{
scope.Dispose();
}
return base.CompleteProcessingMessageAsync(message, result, cancellationToken);
}
}
}
You can the use your custom MessagingProvider in your JobHostConfiguration like
var serviceBusConfig = new ServiceBusConfiguration
{
ConnectionString = config.ServiceBusConnectionString
};
serviceBusConfig.MessagingProvider = new ScopedMessagingProvider(serviceBusConfig, container);
jobHostConfig.UseServiceBus(serviceBusConfig);
After asking my own question about how to handle scoping ... I've just came up to this solution: I don't think this is ideal but I couldn't find any other solution for the moment.
In my example I am dealing with ServiceBusTrigger.
As I am using SimpleInjector, the implementation of the IJobActivator interface looks like that:
public class SimpleInjectorJobActivator : IJobActivator
{
private readonly Container _container;
public SimpleInjectorJobActivator(Container container)
{
_container = container;
}
public T CreateInstance<T>()
{
return (T)_container.GetInstance(typeof(T));
}
}
Here, I am dealing with Triggered webjobs.
So I have two dependencies:
A singleton:
public interface ISingletonDependency { }
public class SingletonDependency : ISingletonDependency { }
And another that need to live only the time my function is triggered:
public class ScopedDependency : IScopedDependency, IDisposable
{
public void Dispose()
{
//Dispose what need to be disposed...
}
}
So in order to have a process that run independently from the webjob. I've encapsulated my process into a class :
public interface IBrokeredMessageProcessor
{
Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token);
}
public class BrokeredMessageProcessor : IBrokeredMessageProcessor
{
private readonly ISingletonDependency _singletonDependency;
private readonly IScopedDependency _scopedDependency;
public BrokeredMessageProcessor(ISingletonDependency singletonDependency, IScopedDependency scopedDependency)
{
_singletonDependency = singletonDependency;
_scopedDependency = scopedDependency;
}
public async Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token)
{
...
}
}
So now when the webjob starts, I need to register my dependencies depending their scopes:
class Program
{
private static void Main()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.RegisterSingleton<ISingletonDependency, SingletonDependency>();
container.Register<IScopedDependency, ScopedDependency>(Lifestyle.Scoped);
container.Register<IBrokeredMessageProcessor, BrokeredMessageProcessor>(Lifestyle.Scoped);
container.Verify();
var config = new JobHostConfiguration
{
JobActivator = new SimpleInjectorJobActivator(container)
};
var servicebusConfig = new ServiceBusConfiguration
{
ConnectionString = CloudConfigurationManager.GetSetting("MyServiceBusConnectionString")
};
config.UseServiceBus(servicebusConfig);
var host = new JobHost(config);
host.RunAndBlock();
}
}
And this is the triggered job:
Only have one dependency : the IoC container. Because this class is part of my composition root, it should be ok.
It handle the scope into the triggered function.
public class TriggeredJob
{
private readonly Container _container;
public TriggeredJob(Container container)
{
_container = container;
}
public async Task TriggeredFunction([ServiceBusTrigger("queueName")] BrokeredMessage message, CancellationToken token)
{
using (var scope = _container.BeginExecutionContextScope())
{
var processor = _container.GetInstance<IBrokeredMessageProcessor>();
await processor.ProcessAsync(message, token);
}
}
}
I've used a couple patterns that rely on the concept of child containers/scopes (depending on the terminology of your IoC container of choice). Not sure which ones support it, but I can tell you that StructureMap 2.6.x and AutoFac do.
The idea is to spin up a child scope for each message coming in, inject any context that's unique to that request, resolve the top-level object from the child scope, and then run your process.
Here's some generalized code showing it with AutoFac. It does do a direct resolve from the container, similar to the anti-pattern you're attempting to avoid, but it's been isolated to one place.
In this case, it's using a ServiceBusTrigger to fire the job, but could be anything - a job host could potentially have a list of these for the different queues/processes.
public static void ServiceBusRequestHandler([ServiceBusTrigger("queuename")] ServiceBusRequest request)
{
ProcessMessage(request);
}
This method is called by all instances of the above methods. It wraps creation of the child scope in a using block to make sure things are cleaned up. Then, any objects that would vary per request and contain context used by other dependencies (user/client information, etc) would be created and injected into the child container (in this example, the IRequestContext). Finally, the component doing the work would be resolved from the child container.
private static void ProcessMessage<T>(T request) where T : IServiceBusRequest
{
try
{
using (var childScope = _container.BeginLifetimeScope())
{
// create and inject things that hold the "context" of the message - user ids, etc
var builder = new ContainerBuilder();
builder.Register(c => new ServiceRequestContext(request.UserId)).As<IRequestContext>().InstancePerLifetimeScope();
builder.Update(childScope.ComponentRegistry);
// resolve the component doing the work from the child container explicitly, so all of its dependencies follow
var thing = childScope.Resolve<ThingThatDoesStuff>();
thing.Do(request);
}
}
catch (Exception ex)
{
}
}
All answers to the question are outdated now. Using the latest packages you can easily get constructor injection right out of the box. Two steps are only required:
Create the event handler function as an instance method in a non-static class. Let's call the class QueueFunctions.
Add your class to the list of services.
builder.ConfigureServices(services =>
{
// Add
// dependencies
// here
services.AddScoped<QueueFunctions>();
});
Now, you'll be able to inject dependencies through the constructor.

Re-implementing WindowManager using ModernUI + Caliburn.Micro combination

Here Caliburn.Micro was successfully combined with ModernUI.
But if we want to use multiple windows we also need to re-implement Caliburn's WindowManager to work properly with ModernUI. How can it be done?
UPDATE:
(Additional question about IoC-Container/Dependency Injection)
Ok, as I get it: I used a Constructor Injection here:
public class BuildingsViewModel : Conductor<IScreen>
{
public BuildingsViewModel(IWindowManager _windowManager)
{
windowManager = _windowManager;
}
}
As far as BuildingsViewModel resolved from IoC container,
container itself injected ModernWindowManager implementation of IWindowManager interface because of this line in Bootstrapper's Configure() method:
container.Singleton<IWindowManager, ModernWindowManager>();
If I resolving an object instance from container, it injects all needed dependencies. Like a tree.
1) So now I wonder how can I replace this line using an injection(with interface)?
_windowManager.ShowWindow(new PopupViewModel());
2) If I want my whole project match DI pattern, all objects instances must be injected into ModernWindowViewModel, that resolves from container first?
3) Is it okay to use Caliburn's SimpleContainer for whole project, or better use mature framework like Castle Windsor? Should I avoid mixing?
UPDATE2:
4) Integrating an IoC container into an existing application requires creating this container first(in Main() method of console app for example), and then all object instanses must grow from it with injected dependencies?
Simply create your own derived WindowManager and override EnsureWindow:
public class ModernWindowManager : WindowManager
{
protected override Window EnsureWindow(object rootModel, object view, bool isDialog)
{
var window = view as ModernWindow;
if (window == null)
{
window = new ModernWindow();
window.SetValue(View.IsGeneratedProperty, true);
}
return window;
}
}
Any views that you want to use as popups must be based on ModernWindow and must either use a LinkGroupCollection or you must set the ContentSource property of the window, otherwise there will be no content.
You could possibly make this View-First but it works ViewModel-First using the method above.
e.g. to popup my PopupView I did the following
PopupView.xaml
<mui:ModernWindow x:Class="TestModernUI.ViewModels.PopupView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" ContentSource="/ViewModels/ChildView.xaml">
</mui:ModernWindow>
PopupViewModel.cs
public class PopupViewModel : Screen
{
// Blah
}
Code to popup the view from another ViewModel:
public void SomeMethod()
{
_windowManager.ShowWindow(new PopupViewModel()); // Or use injection etc
}
Don't forget to register ModernWindowManager in place of WindowManager in your container!
e.g. using CM's SimpleContainer
container.Singleton<IWindowManager, ModernWindowManager>();
Obviously the only downside I can see to the above is that you can't seem to put content directly in a ModernWindow, so you have to have two UserControls for every popup!
A workaround would be to change EnsureWindow in ModernWindowManager so that it created a UserControl based on ModernWindow and set the ContentSource to the URI of the view you want to load, this will trigger the content loader and wire up your ViewModel. I'll update if I get a minute to try it.
Update:
Ok, so at the moment it's very hacky, but this could be a starting point for something useful. Basically I'm generating a URI based on the namespace and name of the view.
I'm sure there is a more reliable way of doing this, but for my test project it works:
protected override Window EnsureWindow(object rootModel, object view, bool isDialog)
{
var window = view as ModernWindow;
if (window == null)
{
window = new ModernWindow();
// Get the namespace of the view control
var t = view.GetType();
var ns = t.Namespace;
// Subtract the project namespace from the start of the full namespace
ns = ns.Remove(0, 12);
// Replace the dots with slashes and add the view name and .xaml
ns = ns.Replace(".", "/") + "/" + t.Name + ".xaml";
// Set the content source to the Uri you've made
window.ContentSource = new Uri(ns, UriKind.Relative);
window.SetValue(View.IsGeneratedProperty, true);
}
return window;
}
My full namespace for my view was TestModernUI.ViewModels.PopupView and the URI generated was /ViewModels/PopupView.xaml which then was loaded and bound via the content loader automagically.
Update 2
FYI here is my Bootstrapper configure method:
protected override void Configure()
{
container = new SimpleContainer();
container.Singleton<IWindowManager, ModernWindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<ChildViewModel>();
container.PerRequest<ModernWindowViewModel>();
container.PerRequest<IShell, ModernWindowViewModel>();
}
Here I create the container, and register some types.
The CM services such as WindowManager and EventAggregator are both registered against their respective interfaces and as singletons so only 1 instance of each will be available at run time.
The view models are registered as PerRequest which creates a new instance every time you request one from the container - this way you can have the same window popup multiple times without strange behaviour!
These dependencies are injected into the constructor of any objects resolved at run time.
Update 3
In answer to your IoC questions:
1) So now I wonder how can I replace this line using an injection(with interface)? _windowManager.ShowWindow(new PopupViewModel());
Since your viewmodels will now usually need dependencies you need to have some way of injecting them into the instances. If PopupViewModel had several dependencies, you could inject them into the parent class but this would couple the parent viewmodel to PopupViewModel in some way.
There are a couple of other methods you can use to get an instance of PopupViewModel.
Inject it!
If you register PopupViewModel as PerRequest you will get a new instance of it every time you request it. If you only need one popup instance in your viewmodel you can just inject it:
public class MyViewModel
{
private PopupViewModel _popup;
private IWindowManager _windowManager;
public MyViewModel(PopupViewModel popup, IWindowManager windowManager)
{
_popup = popup;
_windowManager = windowManager;
}
public void ShowPopup()
{
_windowManager.ShowPopup(_popup);
}
}
The only downside is that the instance will be the same one if you need to use it multiple times in the same viewmodel, though you could inject multiple instances of PopupViewModel if you knew how many you needed at the same time
Use some form of on-demand injection
For dependencies which are required later on you can use on-demand injection such as a factory
I don't think Caliburn or SimpleContainer support factories out of the box, so the alternative is to use IoC.Get<T>. IoC is a static class which lets you access your DI container after instantiation
public void ShowPopup()
{
var popup = IoC.Get<PopupViewModel>();
_windowManager.ShowWindow(popup);
}
You need to make sure you have correctly registered the container in your bootstrapper and delegated any calls to CM's IoC methods to the container - IoC.Get<T> calls the bootstrapper's GetInstance and other methods:
Here's an example:
public class AppBootstrapper : BootstrapperBase {
SimpleContainer container;
public AppBootstrapper() {
Initialize();
}
protected override void Configure() {
container = new SimpleContainer();
container.Singleton<IWindowManager, ModernWindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<IShell, ModernWindowViewModel>();
// Register viewmodels etc here....
}
// IoC.Get<T> or IoC.GetInstance(Type type, string key) ....
protected override object GetInstance(Type service, string key) {
var instance = container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
// IoC.GetAll<T> or IoC.GetAllInstances(Type type) ....
protected override IEnumerable<object> GetAllInstances(Type service) {
return container.GetAllInstances(service);
}
// IoC.BuildUp(object obj) ....
protected override void BuildUp(object instance) {
container.BuildUp(instance);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) {
DisplayRootViewFor<IShell>();
}
Castle.Windsor supports factories so that you can Resolve and Release your components and manage their lifetime more explicitly, but I won't go into that here
2) If I want my whole project match DI pattern, all objects instances must be injected into ModernWindowViewModel, that resolves from container first?
You only need to inject the dependencies that the ModernWindowViewModel needs. Anything that is required by children is automatically resolved and injected e.g.:
public class ParentViewModel
{
private ChildViewModel _child;
public ParentViewModel(ChildViewModel child)
{
_child = child;
}
}
public class ChildViewModel
{
private IWindowManager _windowManager;
private IEventAggregator _eventAggregator;
public ChildViewModel(IWindowManager windowManager, IEventAggregator eventAggregator)
{
_windowManager = windowManager;
_eventAggregator = eventAggregator;
}
}
In the above situation, if you resolve ParentViewModel from the container - the ChildViewModel will get all it's dependencies. You don't need to inject them into the parent.
3) Is it okay to use Caliburn's SimpleContainer for whole project, or better use mature framework like Castle Windsor? Should I avoid mixing?
You can mix, but it might be confusing as they won't work with each other (one container won't know about the other). Just stick with one container, and SimpleContainer is fine - Castle Windsor has a lot more features, but you might never need them (I've only used a few of the advanced features)
4) Integrating an IoC container into an existing application requires creating this container first(in Main() method of console app for example), and then all object instanses must grow from it with injected dependencies?
Yes, you create the container, then you resolve the root component (in 99.9% of applications there is one main component which is called the composition root), and this then builds the full tree.
Here is an example of a bootstrapper for a service based application. I'm using Castle Windsor and I wanted to be able to host the engine in a Windows service or in a WPF application or even in a Console Window (for testing/debug):
// The bootstrapper sets up the container/engine etc
public class Bootstrapper
{
// Castle Windsor Container
private readonly IWindsorContainer _container;
// Service for writing to logs
private readonly ILogService _logService;
// Bootstrap the service
public Bootstrapper()
{
_container = new WindsorContainer();
// Some Castle Windsor features:
// Add a subresolver for collections, we want all queues to be resolved generically
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel));
// Add the typed factory facility and wcf facility
_container.AddFacility<TypedFactoryFacility>();
_container.AddFacility<WcfFacility>();
// Winsor uses Installers for registering components
// Install the core dependencies
_container.Install(FromAssembly.This());
// Windsor supports plugins by looking in directories for assemblies which is a nice feature - I use that here:
// Install any plugins from the plugins directory
_container.Install(FromAssembly.InDirectory(new AssemblyFilter("plugins", "*.dll")));
_logService = _container.Resolve<ILogService>();
}
/// <summary>
/// Gets the engine instance after initialisation or returns null if initialisation failed
/// </summary>
/// <returns>The active engine instance</returns>
public IIntegrationEngine GetEngine()
{
try
{
return _container.Resolve<IIntegrationEngine>();
}
catch (Exception ex)
{
_logService.Fatal(new Exception("The engine failed to initialise", ex));
}
return null;
}
// Get an instance of the container (for debugging)
public IWindsorContainer GetContainer()
{
return _container;
}
}
Once the bootstrapper is created, it sets up the container and registers all services and also plugin dlls. The call to GetEngine starts the application by resolving Engine from the container which creates the full dependency tree.
I did this so that it allows me to create a service or a console version of the application like this:
Service Code:
public partial class IntegrationService : ServiceBase
{
private readonly Bootstrapper _bootstrapper;
private IIntegrationEngine _engine;
public IntegrationService()
{
InitializeComponent();
_bootstrapper = new Bootstrapper();
}
protected override void OnStart(string[] args)
{
// Resolve the engine which resolves all dependencies
_engine = _bootstrapper.GetEngine();
if (_engine == null)
Stop();
else
_engine.Start();
}
protected override void OnStop()
{
if (_engine != null)
_engine.Stop();
}
}
Console App:
public class ConsoleAppExample
{
private readonly Bootstrapper _bootstrapper;
private IIntegrationEngine _engine;
public ConsoleAppExample()
{
_bootstrapper = new Bootstrapper();
// Resolve the engine which resolves all dependencies
_engine = _bootstrapper.GetEngine();
_engine.Start();
}
}
Here's part of the implementation of IIntegrationEngine
public class IntegrationEngine : IIntegrationEngine
{
private readonly IScheduler _scheduler;
private readonly ICommsService _commsService;
private readonly IEngineStateService _engineState;
private readonly IEnumerable<IEngineComponent> _components;
private readonly ConfigurationManager _configurationManager;
private readonly ILogService _logService;
public IntegrationEngine(ICommsService commsService, IEngineStateService engineState, IEnumerable<IEngineComponent> components,
ConfigurationManager configurationManager, ILogService logService)
{
_commsService = commsService;
_engineState = engineState;
_components = components;
_configurationManager = configurationManager;
_logService = logService;
// The comms service needs to be running all the time, so start that up
commsService.Start();
}
All of the other components have dependencies, but I don't inject those into the IntegrationEngine - they are handled by the container

How to avoid passing a reference to the container or using CommonServiceLocator for an EntityFactory

My Entity class has a dependency on a Repository.
public class User
{
private readonly IUserRepository _userRepository;
public User(IUserRepository userRepository)
{
_userRepository = userRepository;
}
...
}
And I have an EntityFactory class used by the Repository to create entities.
public class UserRepository : IUserRepository
{
private readonly EntityFactory _entityFactory;
public UserRepository(EntityFactory entityFactory)
{
_entityFactory = entityFactory;
}
...
}
// EntityFactory #1 with no references or dependencies to DI frameworks or CommonServiceLocator
public class EntityFactory
{
public User InstantiateUser()
{
return new User(); // Requires IUserRepository parameter
}
}
// EntityFactory #2 with reference to Ninject
using Ninject;
public class EntityFactory
{
private readonly IKernel _kernel;
public EntityFactory(IKernel kernel)
{
_kernel = kernel;
}
public User InstantiateUser(IKernel kernel)
{
return new User(_kernel.Get<IUserRepository>());
}
}
// EntityFactory #3 with reference to CommonServiceLocator
using Microsoft.Practices.ServiceLocation;
public class EntityFactory
{
public User InstantiateUser()
{
return new User(ServiceLocator.Current.GetInstance<IUserRepository>());
}
}
Is there a way to avoid the EntityFactory having a reference to the container or using the CommonServiceLocator? (Context Agnostic)
Or am I just designing my classes wrong and the User class should not have a dependency on any Repositories?
Edit: Here is the code using the method from David:
// Ninject binding
Bind<Func<User>>().ToMethod(cxt => () => new User(cxt.Kernel.Get<IUserRepository>()));
// EntityFactory class
private readonly Func<User> _userFactory;
public EntityFactory(Func<User> userFactory)
{
_userFactory = userFactory;
}
public User InstantiateUser()
{
return userFactory.Invoke();
}
Your DI framework should provide you with a method of creating factories:
public class EntityFactory
{
public EntityFactory(Func<User> userFactory) { /* ... */ }
public User InstantiateUser()
{
return userFactory.Invoke();
}
}
When the EntityFactory is created it'll receive a proper User factory which can then be used to create properly resolved users without any reference to the IoC.
What's wrong with option 2 or 3? If you are using IoC or a service locator, you will need to have a reference to it somewhere.
I have a global reference to the IoC container and use that to resolve the interfaces all over the place. This looks a lot like the service locator, but then instead using the IoC container.
I don't believe there is a way around this.

Dependency Injection for Presenter

I have a Presenter that takes a Service and a View Contract as parameters in its constructor:
public FooPresenter : IFooPresenter {
private IFooView view;
private readonly IFooService service;
public FooPresenter(IFooView view, IFooService service) {
this.view = view;
this.service = service;
}
}
I resolve my service with Autofac:
private ContainerProvider BuildDependencies() {
var builder = new ContainerBuilder();
builder.Register<FooService>().As<IFooService>().FactoryScoped();
return new ContainerProvider(builder.Build());
}
In my ASPX page (View implementation):
public partial class Foo : Page, IFooView {
private FooPresenter presenter;
public Foo() {
// this is straightforward but not really ideal
// (IoCResolve is a holder for how I hit the container in global.asax)
this.presenter = new FooPresenter(this, IoCResolve<IFooService>());
// I would rather have an interface IFooPresenter so I can do
this.presenter = IoCResolve<IFooPresenter>();
// this allows me to add more services as needed without having to
// come back and manually update this constructor call here
}
}
The issue is FooPresenter's constructor expects the specific Page, not for the container to create a new one.
Can I supply a specific instance of the view, the current page, to the container for just this resolution? Does that make sense to do, or should I do this another way?
The way to solve passing what I like to call data parameters when resolving dependencies in Autofac is by using generated factories.
(Update: this question discusses the same problem and my article shows how you can avoid large amounts of factory delegates).
The solution to your problem will look something like this:
First, declare a factory delegate thath only accepts the data parameters:
public delegate IFooPresenter FooPresenterFactory(IFooView view);
Your presenter goes unchanged:
public FooPresenter : IFooPresenter {
private IFooView view;
private readonly IFooService service;
public FooPresenter(IFooView view, IFooService service) {
this.view = view;
this.service = service;
}
}
Next the Autofac container setup:
var builder = new ContainerBuilder();
builder.Register<FooService>().As<IFooService>().FactoryScoped();
builder.Register<FooPresenter>().As<IFooPresenter>().FactoryScoped();
builder.RegisterGeneratedFactory<FooPresenterFactory>();
Now in your page you can in two lines of code resolve the presenter by first getting the factory and then calling the factory to do the resolution for you:
public partial class Foo : Page, IFooView {
private FooPresenter presenter;
public Foo() {
var factory = IoCResolve<FooPresenterFactory>();
this.presenter = factory(this);
}
}
I actually solved this exact problem and built a framework around it. I used Autofac parameters to pass existing views to the presenter resolution call.
First, I defined a custom resolution interface derived from Autofac's:
public interface IMvpContext : IContext
{
T View<T>();
}
which allowed me to register a presenter which resolves the view:
builder.RegisterPresenter(c => new FooPresenter(
c.View<IFooView>(),
c.Resolve<IFooService>()));
using an extension method which wraps Autofac's IContext in an implementation of IMvpContext:
public static IConcreteRegistrar RegisterPresenter<T>(
this ContainerBuilder builder,
Func<IMvpContext, T> creator)
{
return builder
.Register((context, parameters) => creator(new MvpContext(context, parameters)))
.FactoryScoped();
}
I defined a parameter type representing the view parameter:
public class MvpViewParameter : NamedParameter
{
public static readonly string ParameterName = typeof(MvpViewParameter).AssemblyQualifiedName;
public MvpViewParameter(object view) : base(ParameterName, view)
{}
}
It uses its own assembly-qualified type name as the parameter name. This has a very low likelihood of conflicting with legitimate parameters.
MvpContext passes all standard resolution calls to the base context. For the view, it resolves the parameter with the well-known name:
public sealed class MvpContext : IMvpContext
{
private IContext _context;
private IEnumerable<Parameter> _resolutionParameters;
public MvpContext(IContext context, IEnumerable<Parameter> resolutionParameters)
{
_context = context;
_resolutionParameters = resolutionParameters;
}
#region IContext
// Pass through all calls to _context
#endregion
#region IMvpContext
public T View<T>()
{
return _resolutionParameters.Named<T>(MvpViewParameter.ParameterName);
}
#endregion
}
The call to resolve the presenter provides the view parameter:
public partial class Foo : Page, IFooView
{
private readonly FooPresenter presenter;
public Foo()
{
this.presenter = IoCResolve<IFooPresenter>(new MvpViewParameter(this));
}
}

Categories