MVC 4 Autofac and Generic Repository pattern - c#

I am utilizing the Unit Of Work and Generic Repository pattern in my MVC 4 app. The problem I am trying to solve is creating Repository stubs for every entity in my system. In order to utilize the Autofac Ioc I am having to create a repository class and interface for every entity so that I can register it in Autofac.
app start...
builder.RegisterType<SchoolDetailRepository>().As<ISchoolDetailRepository>().InstancePerHttpRequest();
Repository class
public class SchoolDetailRepository : RepositoryBase<SchoolDetail>, ISchoolDetailRepository
{
public SchoolDetailRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
{
}
}
Interface
public interface ISchoolDetailRepository : IRepository<SchoolDetail>
{
}
It seems like a lot of extra work.
Is there a way to register the generic repository of Type rather than creating all these empty classes?
Then in my service class I can just have the generic type passed into the constructor via Ioc like...
public class SchoolService : ISchoolService
{
private readonly IRepository<SchoolDetail> _schoolRepository;
private readonly IUnitOfWork _unitOfWork;
public SchoolService(IRepository<SchoolDetail> schoolRepository, IUnitOfWork unitOfWork)
{
this._schoolRepository = schoolRepository;
this._unitOfWork = unitOfWork;
}
}
Container config
// Autofac iOC
var builder = new ContainerBuilder();
// register controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
// register services
builder.RegisterType<MembershipService>().As<IMembershipService>().InstancePerHttpRequest();
builder.RegisterType<SchoolService>().As<ISchoolService>().InstancePerHttpRequest();
builder.RegisterType<StudentService>().As<IStudentService>().InstancePerHttpRequest();
builder.RegisterType<ClassRoomService>().As<IClassRoomService>().InstancePerHttpRequest();
builder.RegisterType<CourseService>().As<ICourseService>().InstancePerHttpRequest();
builder.RegisterType<SchoolYearService>().As<ISchoolYearService>().InstancePerHttpRequest();
builder.RegisterType<EnrollmentService>().As<IEnrollmentService>().InstancePerHttpRequest();
builder.RegisterType<TeacherService>().As<ITeacherService>().InstancePerHttpRequest();
// register data infrastructure
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();
builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerHttpRequest();
// register repositories
builder.RegisterType<SchoolRepository>().As<ISchoolRepository>().InstancePerHttpRequest();
builder.RegisterType<TeacherRepository>().As<ITeacherRepository>().InstancePerHttpRequest();
builder.RegisterType<MembershipRepository>().As<IMembershipRepository>().InstancePerHttpRequest();
builder.RegisterType<RoleRepository>().As<IRoleRepository>().InstancePerHttpRequest();
builder.RegisterType<ProfileRepository>().As<IProfileRepository>().InstancePerHttpRequest();
builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerHttpRequest();
builder.RegisterType<StudentRepository>().As<IStudentRepository>().InstancePerHttpRequest();
builder.RegisterType<ClassRoomRepository>().As<IClassRoomRepository>().InstancePerHttpRequest();
builder.RegisterType<CourseRepository>().As<ICourseRepository>().InstancePerHttpRequest();
builder.RegisterType<EnrollmentRepository>().As<IEnrollmentRepository>().InstancePerHttpRequest();
builder.RegisterType<SchoolYearRepository>().As<ISchoolYearRepository>().InstancePerHttpRequest();
builder.RegisterType<GradeLevelRepository>().As<IGradeLevelRepository>().InstancePerHttpRequest();
//builder.RegisterType<SchoolDetailRepository>().As<ISchoolDetailRepository>().InstancePerHttpRequest();
builder.RegisterGeneric(typeof(RepositoryBase<SchoolDetail>)).As(typeof(IRepository<SchoolDetail>));
// build and setup resolver
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
the exception is coming from the above code where the expression you gave me runs..
builder.RegisterGeneric(typeof(RepositoryBase<SchoolDetail>)).As(typeof(IRepository<SchoolDetail>));
RepositoryBase
public abstract class RepositoryBase<T> where T : class
{
private LearningCompactPilotContext _dataContext;
private readonly IDbSet<T> _dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get; private set;
}
protected LearningCompactPilotContext DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
... more code
}

You need the open generics feature of Autofac:
builder.RegisterGeneric(typeof(RepositoryBase<>))
.As(typeof(IRepository<>));
Then you use your repositories exactly as you described:
public class SomeService
{
private readonly IRepository<SomeEntity> _repository;
public SchoolService(IRepository<SomeEntity> repository)
{
this._repository= repository;
}
}

Related

Derived Class How to inject ?

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.

What is the best way to implement Dependency Injection in Base Controller

I have the follow trouble, in my base controller i do dependency injection. And i have a class child with implementation of base controller and i need pass the constructor. So my doubt is, my way to implementation of dependency injection is correctly?
If no, what is the best way to do this?
I use unity to implementate D.I, and my ide is VS2017 web api 2.
Follow this code i using:
Base controller or parent controller:
public class BaseController : ApiController
{
public string[] includes = null;
private readonly IFiltroServico servico;
public BaseController(IFiltroServico _servico)
{
servico = _servico;
}
}
Base controller to generics types implements Base Controller:
public abstract class BaseController<E, R, F> : BaseController
where E : class
where R : class
where F : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
}
Child controller:
public abstract class BaseController<R> : BaseController
where R : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
//services of controller;
}
You don't need to define the private field servico over and over again as it is already preset in the base controller. Just define it as protected readonly in the base class and use it in the childs.
Other than that your code is fine.
It is perfectly reasonable that a child has the same dependency parameters in the constructor as it inherits behavior of the base class that is most likely relying on the dependency.
Another option would be to use property injection in the base class but you need to add a unity specific attribute to the property. I don't like that as you bind your code directly to Unity.
Have you seen https://simpleinjector.org/index.html
check out git from https://github.com/simpleinjector/SimpleInjector
It is one of the best Inversion of Control library (IOC).
Only thing you need to do is register all your services and types.
using SimpleInjector;
static class Program
{
static readonly Container container;
static Program() {
// 1. Create a new Simple Injector container
container = new Container();
// 2. Configure the container (register)
container.Register<IOrderRepository, SqlOrderRepository>();
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
// 3. Verify your configuration
container.Verify();
}
static void Main(string[] args)) {
// 4. Use the container
var handler = container.GetInstance<CancelOrderHandler>();
var orderId = Guid.Parse(args[0]);
var command = new CancelOrder { OrderId = orderId };
handler.Handle(command);
}
}
Once you register all your types and services you can inject those services where ever you want
public class CancelOrderHandler {
private readonly IOrderRepository repository;
private readonly ILogger logger;
private readonly IEventPublisher publisher;
// Use constructor injection for the dependencies
public CancelOrderHandler(
IOrderRepository repository, ILogger logger, IEventPublisher publisher) {
this.repository = repository;
this.logger = logger;
this.publisher = publisher;
}
public void Handle(CancelOrder command) {
this.logger.Log("Cancelling order " + command.OrderId);
var order = this.repository.GetById(command.OrderId);
order.Status = OrderStatus.Cancelled;
this.repository.Save(order);
this.publisher.Publish(new OrderCancelled(command.OrderId));
}
}
public class SqlOrderRepository : IOrderRepository {
private readonly ILogger logger;
// Use constructor injection for the dependencies
public SqlOrderRepository(ILogger logger) {
this.logger = logger;
}
public Order GetById(Guid id) {
this.logger.Log("Getting Order " + order.Id);
// Retrieve from db.
}
public void Save(Order order) {
this.logger.Log("Saving order " + order.Id);
// Save to db.
}
}
Let me know if you have any queries, Thanks.

Resolving dependencies dynamically using Autofac

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.

Windsor Typed factory to create objects with same dependencies as parent

My Wpf application has a lot of different view models, that depend on repositories and command factories, registered with a transient lifestyle bound to the view model. Commands are created with a typed factory which will always create new instances of dependencies. That can be a problem because of tracking issues in ORMs when the view model depends on a repository and a command that also depends on that repository.
For that reason I want my command factories to create commands with the same instance of repositories as the view model.
How can this be solved by the container without manually creating factories?
Edit - Example with runnable code
public class Service
{
private readonly IRepository repository;
private readonly ICommandFactory commandFactory;
public Service(IRepository repository, ICommandFactory commandFactory)
{
this.repository = repository;
this.commandFactory = commandFactory;
}
public void DoIt()
{
repository.SaveChanges();
commandFactory.Create().Execute();
}
}
public interface ICommandFactory
{
ICommand Create();
}
public interface ICommand
{
void Execute();
}
public class Command : ICommand
{
private readonly IRepository repository;
public Command(IRepository repository)
{
this.repository = repository;
}
public void Execute()
{
repository.SaveChanges();
}
}
public interface IRepository
{
void SaveChanges();
}
public class Repository : IRepository
{
private static int i = 0;
private int instanceNumber = 0;
public Repository()
{
instanceNumber = i++;
Console.WriteLine("Created repository nr: " + instanceNumber);
}
public void SaveChanges()
{
Console.WriteLine("Save changes for repository nr: " + instanceNumber);
}
}
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<Service>().LifestyleTransient());
container.Register(Component.For<IRepository>().ImplementedBy<Repository>().LifestyleBoundTo<object>());
container.Register(Component.For<ICommand>().ImplementedBy<Command>().LifestyleTransient());
container.Register(Component.For<ICommandFactory>().AsFactory().LifestyleTransient());
var service = container.Resolve<Service>();
service.DoIt();
}
}
As you are using transient lifestyle for all dependencies, it is obvious that you have different instances of IRepository in Service and Command classes. What you need, is to increase lifetime of IRepository and probably bind it to lifetime of your service, meaning that the instance of IRepository is created and disposed when the instance of Service is created and disposed.
Castle Windsor has Bound lifestyle:
Somewhere in the graph we have two view models, one depending on the other, and both of them depend on some other service, say a repository. You might want to bind the repository to the subgraph. In other words you might want the entire subgraph of the outermost view model (WelcomeScreenViewModel) to share the same instance of the repository, and to have the repository released when the view model itself is released.
So should register your IRepository in the following way:
Container.Register(Component.For<IRepository>().ImplementedBy<Repository>().LifestyleBoundTo<Service>());
EDIT:
The above solution will not work as ICommand is bound to ICommandFactory not to Service. If you are resolving service instance manually you can use LifestyleScoped:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<Service>().LifestyleTransient());
container.Register(Component.For<IRepository>().ImplementedBy<Repository>().LifestyleScoped());
container.Register(Component.For<ICommand>().ImplementedBy<Command>().LifestyleTransient());
container.Register(Component.For<ICommandFactory>().AsFactory().LifestyleTransient());
using (container.BeginScope())
{
var service = container.Resolve<Service>();
service.DoIt();
}
In this case your IRepository is scoped per scope.
Note To use container.BeginScope() add using Castle.MicroKernel.Lifestyle;

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.

Categories