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.
Related
Long story short, this is the type of controllers that i see in every code base professionally:
//All in One Service interfaces
public class DiController : ControllerBase
{
private readonly IDiService _diService;
public DiController(IDiService diService)
{
_diService = diService;
}
[HttpGet]
public IActionResult GetA()
{
return Ok(_diService.GetA());
}
[HttpGet]
public IActionResult GetB()
{
return Ok(_diService.GetB());
}
}
//Task-based interfaces
public class DiController : ControllerBase
{
private readonly IAService _aService;
private readonly IBService _bService;
public DiController(IAService aService, IBService bService)
{
_aService = aService;
_bService = bService;
}
[HttpGet]
public IActionResult GetA()
{
return Ok(_aService.Handle());
}
[HttpGet]
public IActionResult GetB()
{
return Ok(_bService.Handle());
}
}
Now to keep the post small, imagine that you have one repository for A and other for B, to be used by the service(s). Every component here is Scoped (the same object for every request). Don´t matter what you choose, you end up with a situation like this:
This is in the case of the Task-based interface, and as you can see, you are not using the service B but you get one instance regardless. In the other case you will have the two repositories instantiated.
To solve this problem i used Factories like this:
1 - An abstract class that holds the container and a property that supplies an instance of the Type.
public interface IGenericFactory<out T>
{
T Service { get; }
}
public abstract class GenericFactory<T> : IGenericFactory<T> where T : class
{
private readonly Container _container;
public T Service => _container.GetInstance<T>();
protected GenericFactory(Container container)
{
_container = container;
}
}
2- The interface to be registered in the container
public interface IAServiceFactory : IGenericFactory<IAService>
{
}
3- The class to be registered in the container
public class AServiceFactory : GenericFactory<IAService>, IAServiceFactory
{
public AServiceFactory(Container container) : base(container)
{
}
}
4- Register the factories as Singletons and the services as Scoped/Transient (according to the use case). This would be an example (in Simple Injector) of how the registration for the Task-Based Interface Controller is done:
_container.Register<IAService, AService>(Lifestyle.Scoped);
_container.Register<IBService, BService>(Lifestyle.Scoped);
_container.Register<IAServiceFactory, AServiceFactory>(Lifestyle.Singleton);
_container.Register<IBServiceFactory, BServiceFactory>(Lifestyle.Singleton);
The final product will be this:
An instance of A, and no B.
Is this correct? I have been in projects where you would have a dozen of Services or Repositories, and only one would be used in each call.
Thank you.
You can inject into the action:
public IActionResult About([FromServices] IDateTime dateTime)
{
ViewData["Message"] = $"Current server time: {dateTime.Now}";
return View();
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2#action-injection-with-fromservices
ASP.Net Core Web API
Does the parent class have no empty constructor
derived class Autofac injection ?
If the injection class is added after the parameter, it cannot be used
public class A
{
public A(string e1,string e2){}
}
public class B:A
{
private readonly IProductService _productService;
public B(IProductService productService):base(string e1,string e2)
{
_productService = productService
}
public void test()
{
_productService.AddProduct("");
}
}
AutoFac has no problem configuring
_productService exception occurred
You should try it like this:
public B(IProductService productService, string e1,string e2):base(e1,e2)
{
_productService = productService
}
And then configure Autofac like this for this class registration:
builder.Register(c => new B(c.Resolve<IProductService>(), "e1_val","e2_val"));
If the B class will implement an interface at some point you can use it like this also:
builder.RegisterType<B>().As<IB>()
.WithParameter("e1", "e1value")
.WithParameter("e2", "e2value");
Keep in mind that you have a lot of flexibility with Autofac, please check their documentation at: Autofac Parameters Register for even more information.
Dependency Inversion Principle states that higher level modules should not depend on lower level modules. Both should depend on abstractions. I do understand that principle. But as I'm using ASP.NET MVC, I often get my controller methods as:
public ActionResult MyAction(string userValue)
{
User user = MyDatabase.GetUser();
if (!user.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
user.Update(userValue);
return RedirectToAction("Success");
}
I believe this violates DIP because the result of my controller depends on the User class. In this scenario, I cannot think of a way of decoupling the Controller from my User class. Is there a way to get rid of this dependency? Or is this just fine to do it this way in this scenario?
create an interface and inject an implementation on that to your mvc controller.
public interface IMyDataAccess
{
User GetUser();
}
Create your implementation now.
public class MyMongoDBDataAccess : IMyDataAccess
{
public User GetUser()
{
//return a user from my fancy db
}
}
Now in your controller
public class HomeController : Controller
{
IMyDataAccess dao;
public HomeController(IMyDataAccess myDataAccess)
{
this.dao=myDataAccess;
}
public ActionResult MyAction(string userValue)
{
User user=this.dao.GetUser();
//return something to the view as needed.
}
}
You may use any dependency injection framework like Unity to inject the desired implementation of your interface to your controller.
If you want bring in more layers like Business Layer, Service layer, follow the same thing.
If your application structure is like below, than you are implementing DIP (Dependency Inversion Principle).
DIP says that a layer in your application should depend on a interface, not by an implementation. Like below, Service is depending on IDatabase not MyDatabase
public interface IDatabase {
Update(User user);
}
public interface MyDatabase : IDatabase
{
public Update(User user) {
// update user
}
}
public interface IService {
Update(string user);
}
public class Service : IService
{
private IDatabase _database;
public Service(IDatabase database)
{
_database = database;
}
public Update(User user) {
_database.Update(user);
}
}
DIP also says that high level modules like MvcController don't need to know/depend on low level modules, MyDatabase.
public class MvcController : Controller
{
private IService _service;
private IUserValidator _userValidator;
public MvcController(IService service, IUserValidator userValidator) // depending on abstraction
{
_service = service;
_userValidator = userValidator;
}
public ActionResult MyAction(string userValue)
{
if (!_userValidator.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
User user = _service.GetUser();
user.UserValue = userValue;
_service.Update(user);
return RedirectToAction("Success");
}
}
Note:
I recommend to take a look on 3-tier-architecture doing this you will improve your understanding of SOLID and your application will be more organized.
If in your case MyDatabase is a module Higher then User than, you are not respecting DIP principles, because your Controller make uses of a lower module.
DIP or IoC says High-level modules should not depend on low-level modules. Both should depend on abstractions.
It means that High Level class should not depend on concrete class but it should depend on Interface.
But here you are talking about User class which seems a DTO (Data Transfer Object).
So In that case, You must have to use that DTO in your last layer to either return data or deal with data.
But you should not be using POCO classes provided by entity framework, Instead you should create and use your DTO classes as ViewModels.
Ups, this is how I do it when using ASP.NET Web API, not sure if this works MVC Controller. But there is Unity.MVC (v3 or v4 or v5) lib (Unity.Mvc4) that you can use!
And you can wire it up like this, you should call this code in the Application_Start event!
public static class WebApiBootstrapper
{
public static void Init(IUnityContainer container)
{
GlobalConfiguration.Configure(config =>
{
config.DependencyResolver = new WebApiDependencyResolver(container); // DI container for use in WebApi
config.MapHttpAttributeRoutes();
WebApiRouteConfig.RegisterRoutes(RouteTable.Routes);
});
// Web API mappings
// All components that implement IDisposable should be
// registered with the HierarchicalLifetimeManager to ensure that they are properly disposed at the end of the request.
container.RegisterType<IYourController, YourController>(
new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(IMyDataBase)));
}
}
But before running tthis code you have to register the type mapping
container.RegisterType<IMyDatabse, MyDataBase>();
And you also have to implement the DependencyResolver class:
public class WebApiDependencyResolver : IDependencyResolver
{
protected IUnityContainer container;
public WebApiDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new WebApiDependencyResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
In your controller:
public class YourController : ApiController, IYourController
{
IDataBase _db;
public PlayGroundController(IDataBase db)
{
_db = db;
}
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 am creating an instance of a type scoped to HTTPContextScoped. I am trying to figure out how to inject this specific instance into a property of the same type into an attribute that I don't have control over.
I want to inject the specific instance of UnitOfWork into a property of IUnitOfWork type in an attribute (see code below)
Here is my ObjectFactory.Initialize() method of the part that I am referring to:
ObjectFactory.Initialize(x =>
{
//...
//additional content
//...
x.For<IUnitOfWork>()
.HttpContextScoped()
.Use(context => new UnitOfWork(
context.GetInstance<ISessionFactory>()));
x.SetAllProperties(context =>
{
context.Matching(p =>
p.DeclaringType == typeof(UnitOfWorkAttribute));
context.OfType<IUnitOfWork>();
});
Attribute Class:
public class UnitOfWorkAttribute : ActionFilterAttribute {
public IUnitOfWork UnitOfWork { get; set; }
public UnitOfWorkAttribute() {
Order = 0;
}
public void OnActionExecuting(ActionExecutingContext filterContext) {
UnitOfWork.Begin();
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
UnitOfWork.End();
}
}
I was trying to follow one of Jeremy Miller's examples of using criteria to do so, but I am not doing something right.
Any thoughts of what I am doing incorrectly?
NOTE It does create the UnitOfWork instance as I use it else where, but I am specifically not correctly (or at all) injecting this attribute's property with that instance (or any for that matter).
Try solving this problem by creating a factory for IUnitOfWork objects. Since the lifetime of unit of work instances must be controlled explicly (since you are doing Begin and End, controlling them yourself is much more logical, and adheres the principle of least surprise.
Here is an example of what you can do:
public interface IUnitOfWorkFactory
{
IUnitOfWork NewUnitOfWork();
}
public class MyController : Controller
{
private readonly IUnitOfWorkFactory factory;
public MyController(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public void Operation()
{
using (var work = new this.factory.NewUnitOfWork())
{
work.Begin();
// do some interesting stuff here.
work.End();
}
}
}