I'm working on an application that is split over multiple assemblies. Each of the assemblies provides Interfaces to the outside world, instances are generated via Ninject-based factories.
Ah well, let there be Code. This is from the executing Assembly.
public class IsolationTestModule : NinjectModule
{
public override void Load()
{
ServiceFactory sf = new ServiceFactory();
Bind<IService>().ToMethod(context=>sf.CreatService()).InSingletonScope();
}
}
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
IKernel kernel = new StandardKernel(new IsolationTestModule());
IService service = kernel.Get<IService>();
}
}
The ServiceFactory also relies on Ninject, but has its own Kernel and its own Module:
public interface IService
{
void Idle();
}
public interface IDependantService
{
void IdleGracefully();
}
public class ServiceImpl : IService
{
[Inject]
public IDependantService DependantService { get; set; }
public void Idle()
{
DependantService.IdleGracefully();
}
}
public class DependantServiceImpl : IDependantService
{
public void IdleGracefully() { }
}
public class ServiceFactory
{
private IKernel _kernel = new StandardKernel(new SuppliesModule());
public IService CreatService()
{
return _kernel.Get<IService>();
}
}
public class SuppliesModule : NinjectModule
{
public override void Load()
{
Bind<IService>().To<ServiceImpl>().InSingletonScope();
Bind<IDependantService>().To<DependantServiceImpl>().InSingletonScope();
}
}
What actually happens : All's well until the ServiceFactory has completed to build the ServiceImpl-instance. In the next step, the application's kernel tries to resolve ServiceImpl dependencies via IsolationTestModule and - of course - fails with an exception (no binding available, type IDependantService is not self-bindable). In my understanding the factory's kernel should do that...
Actually I never knew Ninject was that eager to resolve dependencies even in those instances it did not immediately create, which surely opens up new horizons to me ;-)
To temporarily solve this, I change the ServiceImpl to Constructor based injection as depicted below:
public class ServiceImpl : IService
{
public IDependantService DependantService { get; set; }
[Inject]
public ServiceImpl(IDependantService dependantService)
{
DependantService = dependantService;
}
public void Idle()
{
DependantService.IdleGracefully();
}
}
Nevertheless, I would prefer a solution that does not force me to change my Injection strategy. Does anyone have an idea how I can separate the Injection chains?
Your observations are correct. Ninject will do property injection for objects created by ToMethod. Also your solution to use constructor injection is the right way to go. Constructor injection is the perfered way to use Ninject anyway. Property Injection should be used for optional dependencies only.
What you should consider is to use just one kernel. It is very unusual to use multiple kernel instances in an application.
Related
Is it good to resolve the dependencies dynamically like the way i'm doing. Everywhere, it is suggested to use Constructor injection. I really don't understand the drawbacks of doing it the way i'm doing it. Code snippets as below..
Employee.cs
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
IRepository.cs
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
Repository.cs
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
EmployeeController.cs
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
Global.asax
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
var container = builder.Build(Autofac.Builder.ContainerBuildOptions.None);
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
}
Say i've 5 repositories, Constructor injection will resolve all the 5 dependencies for a request i make. I might not use 5 repositories for each and every request. SO i thought of resolving dependencies dynamically by passing the type like i'm doing it in Using<TModel>(). Any suggestions would be appreciated..!! Thank you...!!
Refrain from using the container directly inside your application components; this leads to all kinds of troubles such as maintainability and testability issues. Directly resolving instances from within application code is a well-known anti-pattern known as Service Locator.
As a first refactoring, you can instead apply the Unit of Work pattern. A Unit of Work allows access to underlying repositories. For instance:
public interface IUnitOfWork
{
IRepository<TModel> Repository<TModel>();
}
public sealed class HomeController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._unitOfWork.Repository<Employee>().GetAll();
}
}
Within the Composition Root (where it is allowed to access the container), we can now create an IUnitOfWork implementation that resolves repositories dynamically:
private sealed class AutofacUnitOfWork : IUnitOfWork
{
private readonly IComponentContext _container;
public AutofacUnitOfWork(IComponentContext container)
{
this._container = container;
}
public IRepository<TModel> Repository<TModel>()
{
return _container.Resolve<IRepository<TModel>>();
}
}
This pattern simplifies your application components considerably and prevents downsides that the Service Locator anti-pattern typically causes.
Although applying the Unit of Work pattern might be a useful step into the right direction, an even better approach is to skip the Unit of Work directly and simply inject a required repository directly into application components:
public sealed class HomeController : ApiController
{
private readonly IRepository<Employee> _employeeRepository;
public HomeController(IRepository<Employee> employeeRepository)
{
this._employeeRepository = employeeRepository;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._employeeRepository.GetAll();
}
}
Say i've 5 repositories, Constructor injection will resolve all the 5 dependencies for a request i make. I might not use 5 repositories for each and every request.
Note that from a performance perspective, you should typically not be concerned whether dependencies are used or not. Autofac is in most cases fast enough and it is unlikely that this will actually cause any performance problems in your production systems.
From a design perspective however you should be more worried if a class has many dependencies, while methods just use a few of them. This means that the methods in the class have little cohesion. This is an indication that the class should be split up into multiple smaller classes; it has multiple responsibilities.
Currently i have class Factory which have implemented methods to return instance of Management Service (Some class)
public static class Factory
{
//#region UserNewEditDelete
public static IUserBM UserCreation()
{
return new UserBM();
}
//#endregion
}
What would be the proper way to rewrite this class Factory using Unity Framework?
My vision ::
My Factory :
public static class Factory
{
public static void Register(IUnityContainer container)
{
container.RegisterType<IUserBM, UserBM>();
}
}
Register in Global.asax :
Factory.Register(UnityConfig.GetConfiguredContainer());
when i need to use Management Service :
UnityConfig.Container.Resolve<IUserBM>()
Is it good implementation? Thanks.
Creation of unity container :
var unityContainer = new UnityContainer();
unityContainer.RegisterType<IUserBM, UserBM>();
Usage when you need an instance :
var userBm = unityContainer.Resolve<IUserBM>();
Unity is smart enough to inject that type when needed, for instance :
public class A
{
private IUserBM userBm;
public A(IUserBM userBm)
{
this.userBm = userBm;
}
public void DoSomething()
{
this.userBm.Work();
}
}
// this will construct an instance of class A injecting required types
var a = unityContainer.Resolve<A>();
a.DoSomething();
Unity with ASP.NET MVC
After installing the nuget package Unity.Mvc, edit method RegisterTypes from UnityConfig.cs
public static void RegisterTypes(IUnityContainer container)
{
unityContainer.RegisterType<IUserBM, UserBM>();
}
Now if you need an instance of IUserBm in a controller, add a constructor argument :
public class HomeController : Controller
{
private IUserBm userBm;
public HomeController(IUserBm userBm)
{
this.userBm = userBm;
}
...
Unity will create the controller for you providing an instance of the registered type thanks to UnityDependencyResolver automatically set up when you install the package.
For more information, see ASP.NET MVC 4 Dependency Injection
I have my controller like this
public class MyController : Controller
{
private IEntityRepository accountsRepo;
private IEntityRepository dataRepo;
public MyController(IEntityRepository accs, IEntityRepository data)
{
accountsRepo = accs;
dataRepo = data;
}
.....
}
And I installed container this way:
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IEntityRepository>()
.ImplementedBy<AccountsRepository>()
.Named("accs")
.LifestyleTransient(),
Component.For<IEntityRepository>()
.ImplementedBy<DataRepository>()
.Named("data")
.LifestyleTransient());
}
}
Also I have facilities setted up:
public class PersistenceFacility : AbstractFacility
{
protected override void Init()
{
Kernel.Register(
Component.For<DbContext>()
.ImplementedBy<AccountsContext>()
.LifestylePerWebRequest(),
Component.For<DbContext>()
.ImplementedBy<DataContext>()
.LifestylePerWebRequest());
}
}
}
...and installed:
public class PersistenceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<PersistenceFacility>();
}
}
So when I'm using my controller both parameters are injected with AccountsRepository instance (which was registered first). Of course I wanna see "data" being DataRepository respectively. Please, explain me proper way to deal with this kind of injection.
EDIT
As #roman suggested I have implemented generic repositories:
public interface IRepository : IDisposable
{
void SaveChanges();
void ExecuteProcedure(String procedureCommand, params SqlParameter[] sqlParams);
}
public interface IEntityRepository<T> : IRepository
{
T Context { get; set; }
DbSet<TEntity> Set<TEntity>() where TEntity : class;
}
public class AccountsRepository : IEntityRepository<AccountsContext>
{
public AccountsContext Context { get; set; }
public AccountsRepository(AccountsContext c)
{
Context = c;
}
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
return Context.Set<TEntity>();
}
public virtual void ExecuteProcedure(String procedureCommand, params SqlParameter[] sqlParams)
{
Context.Database.ExecuteSqlCommand(procedureCommand, sqlParams);
}
public virtual void SaveChanges()
{
Context.SaveChanges();
}
public void Dispose()
{
if (Context != null)
Context.Dispose();
}
}
DataRepository looks the same way, my be at some point I will decide to have just one concrete class EntityRepository, but it not relevant to exceptions I receiving.
So after cosmetic interfaces changes my contreller become:
public class HomeController : Controller
{
private IEntityRepository<AccountsContext> accountsRepo;
private IEntityRepository<DataContext> dataRepo;
public HomeController(IEntityRepository<AccountsContext> accs, IEntityRepository<DataContext> data)
{
accountsRepo = accs;
dataRepo = data;
}
....
}
Also I have changed installer code:
container.Register(
Component.For<IEntityRepository<AccountsContext>>()
.ImplementedBy<AccountsRepository>()
.LifestyleTransient(),
Component.For<IEntityRepository<DataContext>>()
.ImplementedBy<DataRepository>()
.LifestyleTransient());
And now during controller resolving proccess
return (IController) kernel.Resolve(controllerType);
I catching
Can't create component 'MyMVCProj.DAL.AccountsRepository' as it has dependencies to be satisfied.
'MyMVCProj.DAL.AccountsRepository' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'MyMVCProj.DAL.AccountsRepository' as it has dependencies to be satisfied.
'MyMVCProj.DAL.AccountsRepository' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.
But I have installed AccountsContext in facility logic.
EDIT++
According to #Roman suggestion I have tweaked my facility this way:
public class PersistenceFacility : AbstractFacility
{
protected override void Init()
{
Kernel.Register(
Component.For<DbContext>()
.ImplementedBy<AccountsContext>()
.Named("accctx")
.LifestylePerWebRequest(),
Component.For<DbContext>()
.ImplementedBy<DataContext>()
.Named("datactx")
.LifestylePerWebRequest());
}
}
and also repositories installler:
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IEntityRepository<AccountsContext>>()
.ImplementedBy<AccountsRepository>()
.Named("accs")
.LifestyleTransient()
.DependsOn(Dependency.OnComponent(typeof (DbContext), "accctx")),
Component.For<IEntityRepository<DataContext>>()
.ImplementedBy<DataRepository>()
.Named("data")
.LifestyleTransient()
.DependsOn(Dependency.OnComponent(typeof (DbContext), "datactx")));
}
}
This is the exception I get now:
Can't create component 'accs' as it has dependencies to be satisfied.
'accs' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.
But trying to solve this brute forcing the code I ended with working solution, just installing concrete implementations of DBContext:
public class PersistenceFacility : AbstractFacility
{
protected override void Init()
{
Kernel.Register(
Component.For<AccountsContext>().LifestylePerWebRequest(),
Component.For<DataContext>().LifestylePerWebRequest());
}
}
And kernel's components now are:
AccountsContext PerWebRequest
AccountsRepository / IEntityRepository<AccountsContext> Transient
DataContext PerWebRequest
DataRepository / IEntityRepository<DataContext> Transient
And before they were:
AccountsContext / DbContext PerWebRequest
AccountsRepository / IEntityRepository<AccountsContext> Transient
DataContext / DbContext PerWebRequest
DataRepository / IEntityRepository<DataContext> Transient
So the new questions are:
Have I did all stuff idiomatically?
Why this behaviour - there already was AccountContext with little mention of it dependencies.
The fact that you expect two instances of same interface, yet you require different behavior for them (by injecting them to two different parameters), implies - in my opinion - that they shouldn't be the same interface, because they have different roles, or responsibilities. It would make sense to me more, if IEntityRepository was a generic class and then you would require in MyController two different generic interface types:
public class MyController(IEntityRepository<Account> acc, IEntityRepository<Data> data)
Nevertheless, If you still want to do that kind of thing, I suggest you use a CollectionResolver that will allow MyController class to get an IEnumerable. That way you'll get both instances, but it'll be up to you to select the appropriate one to use depending on your needs, which I'll stress again, I think is the wrong approach for this.
To use CollectionResolver you need to register it with the Windsor container like this:
var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
And then, MyController will look like this:
public class MyController(IEnumerable<IEntityRepository> repositories)
{
accountsRepo = repositories.Where(...);
dataRepo = repositories.Where(...);
}
I have WinForm application and I want to use ServiceStack dependency injection mechanism:
public class AppHost : AppHostBase
{
public AppHost()
: base("MyName", typeof(AppHost).Assembly)
{
}
public override void Configure(Container container)
{
container.RegisterAutoWiredAs<AppApplicationContext, IAppApplicationContext>();
}
}
Then in some form class use it:
public class SomeClass : AppBaseForm
{
public IAppApplicationContext AppApplicationContext { get; set; }
public SomeClass(IAppApplicationContext appApplicationContext)
{
AppApplicationContext = appApplicationContext;
}
public SomeClass()
{
}
}
But AppApplicationContext is always null. When in parameterless constructor I write:
AppApplicationContext = AppHostBase.Resolve<IAppApplicationContext>();
then every thing is OK. But is this right way to do that? I mean AppApplicationContext should not be resolved by IoC automatically? And WinForm must have parameterless constructor.
Rest of code:
private static void Main()
{
var appHost = new AppHost();
appHost.Init();
}
public interface IAppApplicationContext
{
}
public class AppApplicationContext : IAppApplicationContext
{
}
You need to call AutoWire to have the container inject the dependancies. You can use it in your WinForm app like this:
public class SomeClass : AppBaseForm
{
public IAppApplicationContext AppApplicationContext { get; set; }
public SomeClass()
{
// Tell the container to inject dependancies
HostContext.Container.AutoWire(this);
}
}
When you use a regular ServiceStack service, the AutoWire happens behind the scenes during the request pipeline when ServiceStack creates an instances of your Service.
I have created a fully working example here. Note: The demo is just a console application, not WinForms but it does shows the IoC being used outside of the ServiceStack service, and it works no differently.
I have been trying to configure Windsor to provide a different implementation for a service depending on which class is being constrcuted:
I have read this
http://docs.castleproject.org/Windsor.Registering-components-one-by-one.ashx#Supplying_the_component_for_a_dependency_to_use_Service_override_9
and asked this yesterday
Windsor Ioc container: How to register that certain constructors take different implementation of an interface
The answer to that question works correctly when I resolve the class directly, but not when it is in an object graph a few levels deep, and the class I want to override is used as a default implementation of another interface in a different registration
e.g.
I have 2 MVC controllers. One for logging and one for cardpayments. The logging one takes a logging provider which in turn takes an IService. The CardPaymentController takes a card payment provider which in turn takes an IService. The CardPaymentProvider should get a secure service and the logging provider a normal service
code is below:
Registrations:
Component.For<ILoggingProvider>().ImplementedBy<LoggingProvider>(),
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<IService>().ImplementedBy<WebService>().Named("default"),
Component.For<IService>().ImplementedBy<SecureWebService>().Named("secure"),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
Component.For<LoggingProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("default"))
Class hierarchy:
public LoggingController(ILoggingProvider loggingProvider)
{
this.loggingProvider = loggingProvider;
}
public CardPaymentController(ICardPaymentProvider cardPaymentProvider)
{
this.cardPaymentProvider = cardPaymentProvider;
}
public interface IService
{
void Doit();
}
public class WebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class SecureWebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class CardPaymentProvider : ICardPaymentProvider
{
private readonly IService service;
public CardPaymentProvider(IService service)
{
this.service = service;
}
}
public interface ICardPaymentProvider
{
}
public class LoggingProvider : ILoggingProvider
{
private readonly IService service;
public LoggingProvider(IService service)
{
this.service = service;
}
}
public interface ILoggingProvider
{
}
This produces an error on start up:
"There is a component already registered for the given key Spike.CardPaymentProvider"
If I add Named("somename") to either the CardPaymentProvider registration or the ICardPaymentProvider registration, then it starts OK, but doesn't provide a secure implementation of the service to the CardPaymentProvider - just a normal version.
What am I doing wrong?
You have to define the service overrides in the same registration. Instead of:
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
do:
Component.For<ICardPaymentProvider>()
.ImplementedBy<CardPaymentProvider>()
.ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),