autofac binding to a repository that inherits a base repo [duplicate] - c#

I am trying to use autofac with a repository and I am trying to add a little generics to try reducing the amount of duplicate code I am writing.However I am going round in circles trying to get autofac to work for me
So I created a domainservice and interface that handles our the standard crud operations
public class DomainService<T>:IDomainService<T>
{
protected readonly IDomainService<T> Repository;
public DomainService(IDomainService<T> repository)
{
Repository = repository;
}
public IQueryable<T> GetQueryable()
{
return Repository.GetQueryable();
}
public virtual Task<T> Add(T entity)
{
return Repository.Add(entity);
}
Interface:
public interface IDomainService<T>
{
IQueryable<T> GetQueryable();
Task<T> Add(T entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
Task<T> GetById(int id);
Task<T> GetByUID(Guid id);
}
I am using my repo is nothing special
public class SkillRepository : DomainService<Skill>, ISkill
{
private DataContext _db = new DataContext();
private readonly ILogger _log = null;
public SkillRepository(IDomainService<Skill> repository, ILogger log) : base(repository)
{
_log = log;
}
}
Finally where I wire up autofac:
var builder = new ContainerBuilder();
// Register the Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register other dependencies.
builder.Register(c => new Logger()).As<ILogger>().InstancePerApiRequest();
builder.RegisterType<SkillRepository>()
.As<IDomainService<Skill>>()
.As<ISkill>()
.InstancePerRequest();
// Build the container.
var container = builder.Build();
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
My web api controller looks like
public class SkillsController : BaseController<Skill>
{
private readonly ISkill _skillRepository;
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
{
_skillRepository = skillRepository;
}
}
BaseController
public abstract class BaseController<TEntity> : ApiController
where TEntity : new()
{
protected readonly IDomainService<TEntity> DomainService;
protected BaseController(IDomainService<TEntity> domainService)
{
DomainService = domainService;
}
I get an exception:
"None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'Api.EndPoints.Skills.SkillsController' can be invoked with the
available services and parameters:\ \ Cannot resolve parameter
'Domain.Repository.SkillRepository skillRepository' of constructor
'Void .ctor(Domain.Repository.SkillRepository)'."
Is there something obvious that I am doing wrong?

It cannot resolve the dependency because it's looking for the concrete type but you never registered SkillsRepository as that. Now you could change the registration to register the concrete type but that wouldn't be the best approach.
A better approach is to register SkillsRepository as its interfaces:
builder.RegisterType<SkillRepository>()
.As<ISkillsRepository>()
.InstancePerRequest();
And define ISkillsRepository to inherit all the other interfaces like ISkill that you want.
public interface ISkillsRepository : ISkill, IDomainService<Skill> { }
Don't register objects as concrete types and don't depend on concrete types in constructors.
public SkillsController(ISkillRepository skillRepository) :
base(skillRepository) ...
If you use concrete types as dependencies you create classes that cannot be tested using mocking frameworks.
Your use of SkillRepository : DomainService<Skill>, ISkill is perplexing too. Why is it both a skill and a domain service for skills? Doesn't make much sense.

Exception clearly states:
Cannot resolve parameter 'Domain.Interfaces.ISkill skillRepository' of constructor 'Void .ctor(Domain.IDomainService`1[Model.Skill], Domain.Interfaces.ISkill)'.
You have only IDomainService registered. But no ISkill (the line is commented).
Also why does the ctor require 2 parameters? SkillRepository implements both IDomainService<Skill> and ISkill so you should be able to pass it along:
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
P.S.
I'd name it this way:
public class SkillRepository : ISkillRepository, IDomainService<Skill>
And I prefer everything to be either plural (SkillsControllers, SkillsRepository) or everything singular (SkillController, SkillRepository).

In my opinion you should first sort out names for your classes which is making it hard to understand the code itself. secondly your repository is implementing domain service interface and ISkill and things like that is adding more confusion. i am pretty sure if you organise your classes properly then you will find solution to your problem.
For instance ApiController should use domain service, domain service should use repository and repository should deal with enties.
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(string name){}
public void DeleteSkillById(int id){}
..... etc
}
public class Repository:IRepository
{
public T Get(int id){}
public IEnumerable<T>GetAll(){}
}
Then you need to bind your interfaces to concrete classed in ioc. things should work that way i am pretty sure.

Related

Simple Injector - Inject service based on the specified generic type at runtime

I was a long time user of Autofac that recently switched to Simple Injector for my DI container needs. When I used Autofac, I was able to do something I'm still not able to do with Simple Injector, maybe because I do not yet perfectly understand the API.
Let's say I have the service IEntityRepository of TEntity and TDbContext. It's implementation looks like that:
public class EntityRepository<TEntity, TDbContext> : IEntityRepository<TEntity, TDbContext>
where TDbContext : IEntityDbContext where TEntity : class
{
public EntityRepository(TDbContext dbContext)
{
}
}
With Autofac, I was able to register the open generic implementation EntityRepository as the open generic interface IEntityRepository, so when I would inject say, IEntityRepository of Product and IProductsDbContext, the DI container would automatically guess that I inject through the constructor an instance of ProductsDbContext.
Is this possible with Simple Injector? I tries these, but it still fails:
container.Register(typeof(IEntityRepository<,>), typeof(EntityRepository<,>).Assembly);
container.Register(typeof(IEntityRepository<,>), typeof(EntityRepository<,>));
Thanks in advance for you help!
EDIT:
So here's a full exemple with Autofac as requested by Steven. Create a new .NET Core Console Application. You'll need to install the NuGet Package Autofac.
Program.cs:
internal class Program
{
private static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<ProductsDbContext>().AsImplementedInterfaces();
builder.RegisterGeneric(typeof(EntityRepository<,>)).As(typeof(IEntityRepository<,>));
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var productsRepository = scope.Resolve<IEntityRepository<Product, IProductsDbContext>>();
Console.WriteLine($"Resolved IEntityRepository is of type: {productsRepository.GetType()}");
}
}
}
ProductsDbContext.cs
public class ProductsDbContext : IProductsDbContext
{
public void Dispose()
{
// Demo, do nothing.
}
public int SaveChanges()
{
throw new System.NotImplementedException();
}
}
Product.cs
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
EntityRepository.cs
public class EntityRepository<TEntity, TDbContext> : IEntityRepository<TEntity, TDbContext>
where TDbContext : IEntityDbContext where TEntity : class
{
private readonly TDbContext _dbContext;
public EntityRepository(TDbContext dbContext)
{
_dbContext = dbContext;
Console.WriteLine($"Database context is of type {dbContext.GetType()}.");
}
public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> whereClause)
{
throw new NotImplementedException();
}
}
IEntityDbContext.cs
public interface IEntityDbContext : IDisposable
{
int SaveChanges();
}
IProductsDbContext.cs
public interface IProductsDbContext : IEntityDbContext
{
}
IEntityRepository.cs
public interface IEntityRepository<TEntity, TDbContext> where TDbContext : IEntityDbContext where TEntity : class
{
IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> whereClause);
}
The final console output should ressemble to:
Database context is of type
GenericTypeDiTester.DbContexts.ProductsDbContext. Resolved
IEntityRepository is of type:
GenericTypeDiTester.Repositories.EntityRepository`2[GenericTypeDiTester.Models.Product,GenericTypeDiTester.Interfaces.DbContexts.IProductsDbContext]
You can download the full example there: https://drive.google.com/file/d/1UkIYxLsY6YGwo5jOB5TyyncXc6yho8X5/view?usp=sharing
EDIT 2:
The problem wasn't with the Simple Injector library at the end. It seems that mixing the usage of Microsoft.DependencyInjection and SimpleInjector isn't really a good thing. As suggested by Steven, you should exclusively use SI to register the majority of your services and in rare case, MS.DI (by example for using AddDbContext).
As for my part, I have in my project MediatR, a library that implements the Mediator pattern. This library offers a NuGet package with an extension method AddMediatR for the IServiceCollection of MS.DI, which is supposed to register all handlers properly, but it wasn't the case for me. So I ended up registering the module all by myself using SI.
At the end it everything worked perfectly. You really need to call these lines at the end of the registering process: EnableSimpleInjectorCrossWiring and UseSimpleInjectorAspNetRequestScoping. Nothing else must be registered using the IServiceCollection afterwards. That way, the cross wiring of both DI framework ends up to work beautifully.
The way to register this in Simple Injector is:
container.Register(typeof(IEntityRepository<,>), typeof(EntityRepository<,>));
container.Register<IProductsDbContext, ProductsDbContext>();
There is no AsImplementedInterfaces equivalent in Simple Injector, although there are several ways to achieve rhe same. In the case that ProductsDbContext has multiple interfaces that need to be registered, the most obvious way is to register each interface explicitly:
container.Register<IProductsDbContext, ProductsDbContext>();
container.Register<IUsersDbContext, ProductsDbContext>();
container.Register<ICustomersDbContext, ProductsDbContext>();

Determining which implementation to inject at runtime using .NET Core dependency injection

I have three types of users in my application, let's say Type1, Type2 and Type3.
Then i want to create one service implementation for each type, let's say i have a service to get photos, i would have three services : Type1PhotosService, Type2PhotosService and Type3PhotosService, each of them implementing IPhotosService.
In the web api, i would inject IPhotosService :
IPhotosService _service;
public PhotosController(IPhotosService service){
_service = service;
}
The web api uses token authentication with claims. So what i want to achieve, is for each user, depending on the claim he has : type1 or type2 or type3, the correct implementation of the service will be automatically injected rather than injecting a single service in the startup file.
What i want to avoid, is having one service, with a bunch of switch and if statements to return the correct data depending on user type and the roles he has.
EDIT:
some comments were wondering what's the point of three implementations, so here are more details to give it a little more sense.
The service is a job finder service, and the application has three different profiles : candidate, employer and administration. Each of these profiles need a proper implementation. So rather than having three methods GetCandidateJobs, GetEmployerJobs and GetAdministrationJobs inside the same service and switch on the user type, i preferred to have one implementation per profile type, then depending on the profile type, use the correct implementation.
Without Using a Separate IoC Container
Here's an approach that's way easier than configuring your app to use another IoC container and then configuring that container. After working through this with Windsor this solution seems a whole lot easier.
This approach is simplest if you can use a singleton instance of each service implementation.
We'll start with an interface, some implementations, and the factory we can inject which will return an implementation selected at runtime based on some input.
public interface ICustomService { }
public class CustomServiceOne : ICustomService { }
public class CustomServiceTwo : ICustomService { }
public class CustomServiceThree : ICustomService { }
public interface ICustomServiceFactory
{
ICustomService Create(string input);
}
Here's a really crude implementation of the factory. (Didn't use string constants, or polish it at all.)
public class CustomServiceFactory : ICustomServiceFactory
{
private readonly Dictionary<string, ICustomService> _services
= new Dictionary<string, ICustomService>(StringComparer.OrdinalIgnoreCase);
public CustomServiceFactory(IServiceProvider serviceProvider)
{
_services.Add("TypeOne", serviceProvider.GetService<CustomServiceOne>());
_services.Add("TypeTwo", serviceProvider.GetService<CustomServiceTwo>());
_services.Add("TypeThree", serviceProvider.GetService<CustomServiceThree>());
}
public ICustomService Create(string input)
{
return _services.ContainsKey(input) ? _services[input] : _services["TypeOne"];
}
}
This assumes that you've already registered CustomServiceOne, CustomServiceTwo, etc. with the IServiceCollection. They would not be registered as interface implementations, since that's not how we're resolving them. This class will simply resolve each one and put them in a dictionary so that you can retrieve them by name.
In this case the factory method takes a string, but you could inspect any type or multiple arguments to determine which implementation to return. Even the use of a string as the dictionary key is arbitrary. And, just as an example, I provided fallback behavior to return some default implementation. It might make more sense to throw an exception instead if you can't determine the right implementation to return.
Another alternative, depending on your needs, would be to resolve the implementation within the factory when it's requested. To the extent possible I try to keep most classes stateless so that I can resolve and reuse a single instance.
To register the factory with the IServiceCollection at startup we would do this:
services.AddSingleton<ICustomServiceFactory>(provider =>
new CustomServiceFactory(provider));
The IServiceProvider will be injected into the factory when the factory is resolved, and then the factory will use it to resolve the service.
Here's the corresponding unit tests. The test method is the identical to the one used in the Windsor answer, which "proves" that we can transparently replace one factory implementation with another and change other stuff in the composition root without breaking stuff.
public class Tests
{
private IServiceProvider _serviceProvider;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddSingleton<CustomServiceOne>();
services.AddSingleton<CustomServiceTwo>();
services.AddSingleton<CustomServiceThree>();
services.AddSingleton<ICustomServiceFactory>(provider =>
new CustomServiceFactory(provider));
_serviceProvider = services.BuildServiceProvider();
}
[TestCase("TypeOne", typeof(CustomServiceOne))]
[TestCase("TypeTwo", typeof(CustomServiceTwo))]
[TestCase("TYPEThree", typeof(CustomServiceThree))]
[TestCase("unknown", typeof(CustomServiceOne))]
public void FactoryReturnsExpectedService(string input, Type expectedType)
{
var factory = _serviceProvider.GetService<ICustomServiceFactory>();
var service = factory.Create(input);
Assert.IsInstanceOf(expectedType, service);
}
}
As in the Windsor example, this is written to avoid any reference to the container outside of the composition root. If a class depends on ICustomServiceFactory and ICustomService you could switch between this implementation, the Windsor implementation, or any other implementation of the factory.
Using Windsor
I'm going to sidestep the questions about whether or not this makes sense in this case and just attempt to answer the question as asked:
.NET Core's IoC container isn't built particularly well for this sort of scenario. (They acknowledge this in their documentation.) You can work around it by adding another IoC container like Windsor.
The implementation ended up looking way more complicated than I would have liked, but once you get past the setup it's not bad and you get access to Windsor's features. I'm going to provide another answer that doesn't include Windsor. I had to do all of this work to see that I probably like the other approach better.
In your project, add the Castle.Windsor.MsDependencyInjection NuGet package.
Interfaces and Implementations for Testing
For testing, I added some interfaces and implementations:
public interface ICustomService { }
public interface IRegisteredWithServiceCollection { }
public class CustomServiceOne : ICustomService { }
public class CustomServiceTwo : ICustomService { }
public class CustomServiceThree : ICustomService { }
public class RegisteredWithServiceCollection : IRegisteredWithServiceCollection { }
The intent is to create a factory that will select and return an implementation of ICustomService using some runtime input.
Here's an interface which will serve as a factory. This is what we can inject into a class and call at runtime to get an implementation of ICustomService:
public interface ICustomServiceFactory
{
ICustomService Create(string input);
}
Configure the Windsor Container
Next is a class which will configure an IWindsorContainer to resolve dependencies:
public class WindsorConfiguration : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<ICustomService, CustomServiceOne>().Named("TypeOne"),
Component.For<ICustomService, CustomServiceTwo>().Named("TypeTwo"),
Component.For<ICustomService, CustomServiceThree>().Named("TypeThree"),
Component.For<ICustomService, CustomServiceOne>().IsDefault(),
Component.For<ICustomServiceFactory>().AsFactory(new CustomServiceSelector())
);
}
}
public class CustomServiceSelector : DefaultTypedFactoryComponentSelector
{
public CustomServiceSelector()
: base(fallbackToResolveByTypeIfNameNotFound: true) { }
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return (string) arguments[0];
}
}
Here's what's going on in here:
The TypedFactoryFacility will enable us to use Windsor's typed factories. It will create an implementation of our factory interface for us.
We're registering three implementations of ICustomService. Because we're registering more than one implementation, each must have a name. When we resolve ICustomService we can specify a name, and it will resolve the type according to that string.
For illustration I registered another implementation of ICustomService without a name. That will enable us to resolve a default implementation if we try to resolve using an unrecognized name. (Some alternatives are just throwing an exception, or returning a "null" instance of ICustomService or creating a class like UnknownCustomService that throws an exception.)
Component.For<ICustomServiceFactory>().AsFactory(new CustomServiceSelector()) tells the container to create a proxy class to implement ICustomServiceFactory. (More on that in their documentation.)
CustomServiceSelector is what takes the argument passed to the factory's Create method and returns the component name (TypeOne, TypeTwo, etc.) that will be used to select a component. In this case we're expecting that the argument passed to the factory will be the same as the registration name we've used. But we could replace this with other logic. Our factory could even take arguments of other types which we could inspect and determine which string to return.
Configure Your App To Use the Windsor Container
Now, in StartUp, modify ConfigureServices to return IServiceProvider instead of void and create an IServiceProvider that combines services registered directly with the IServiceCollection with those registered with the Windsor container:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var container = new WindsorContainer();
container.Install(new WindsorConfiguration());
return WindsorRegistrationHelper.CreateServiceProvider(container, services);
}
container.Install(new WindsorConfiguration()) allows WindsorConfiguration to configure our container. We could just configure the container right in this method, but this is a nice way to keep our container configurations organized. We can create numerous IWindsorInstaller implementations or our own custom classes to configure the Windsor container.
WindsorRegistrationHelper.CreateServiceProvider(container, services) creates the IServiceProvider that uses container and services.
Does It Work?
I wouldn't post all this without finding out first. Here's some NUnit tests. (I usually write some basic tests for DI configuration.)
The setup creates an IServiceProvider similar to what would happen in the application startup. It creates a container and applies the WindsorConfiguration. I'm also registering a service directly with the ServiceCollection to make sure that the two play well together. Then I'm combining the two into an IServiceProvider.
Then I'm resolving an ICustomerServiceFactory from the IServiceProvider and verifying that it returns the correct implementation of ICustomService for each input string, including the fallback when the string isn't a recognized dependency name.
I'm also verifying that the service registered directly with ServiceCollection is resolved.
public class Tests
{
private IServiceProvider _serviceProvider;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddSingleton<IRegisteredWithServiceCollection, RegisteredWithServiceCollection>();
var container = new WindsorContainer();
container.Install(new WindsorConfiguration());
_serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(container, services);
}
[TestCase("TypeOne", typeof(CustomServiceOne))]
[TestCase("TypeTwo", typeof(CustomServiceTwo))]
[TestCase("TYPEThree", typeof(CustomServiceThree))]
[TestCase("unknown", typeof(CustomServiceOne))]
public void FactoryReturnsExpectedService(string input, Type expectedType)
{
var factory = _serviceProvider.GetService<ICustomServiceFactory>();
var service = factory.Create(input);
Assert.IsInstanceOf(expectedType, service);
}
[Test]
public void ServiceProviderReturnsServiceRegisteredWithServiceCollection()
{
var service = _serviceProvider.GetService<IRegisteredWithServiceCollection>();
Assert.IsInstanceOf<RegisteredWithServiceCollection>(service);
}
}
Is All of This Worth It?
Now that I've figured it out, I'd probably use it if I really needed this sort of functionality. It looks worse if you're trying to assimilate both using Windsor with .NET Core and seeing it's abstract factory implementation for the first time. Here's another article with some more information on Windsor's abstract factory without all the noise about .NET Core.
I am going to go out on a limb here and say that the attempt to utilize dependency injection for this purpose is sub-optimal. Normally this would be handled by a Factory pattern that produces service implementations using the dreaded if and switch statements. A simple example is:
public interface IPhotoService {
Photo CreatePhoto(params);
}
public class PhotoServiceFactory {
private readonly IPhotoService _type1;
private readonly IPhotoService _type2;
private readonly IPhotoService _type3;
public PhotoServiceFactory(IDependency1 d1, IDependency2 d2, ...etc) {
_type1 = new ConcreteServiceA(d1);
_type2 = new ConcreteServiceB(d2);
_type3 = new ConcreteServiceC(etc);
}
public IPhotoService Create(User user) {
switch(user.Claim) {
case ClaimEnum.Type1:
return _type1;
case ClaimEnum.Type2:
return _type2;
case ClaimEnum.Type3:
return _type3;
default:
throw new NotImplementedException
}
}
}
Then in your controller:
public class PhotosController {
IPhotoServiceFactory _factory;
public PhotosController(IPhotoServiceFactory factory){
_factory = factory;
}
public IHttpActionResult GetPhoto() {
var photoServiceToUse = _factory.Create(User);
var photo = photoServiceToUse.CreatePhoto(params);
return Ok(photo);
}
}
Alternately just use the concrete classes as arguments in the constructor and follow a similar logic as to the above.
Here is one solution, i have created inside asp.net core console application.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace CreationalPattern
{
class Program
{
static void Main(string[] args)
{
// Add dependency into service collection
var services = new ServiceCollection()
.AddTransient<FordFigoFactory>()
.AddTransient<AudiQ7Factory>();
/* Create CarServiceFactory as singleton because it can be used across the application more frequently*/
services.AddSingleton<ICarServiceFactory>(provider => new CarServiceFactory(provider));
// create a service provider from the service collection
var serviceProvider = services.BuildServiceProvider();
/* instantiate car*/
var factory = serviceProvider.GetService<ICarServiceFactory>();
var audiCar = factory.Create("audi").CreateACar("Blue");
Console.Read();
}
}
public interface ICarServiceFactory
{
ICreateCars Create(string input);
}
public class CarServiceFactory : ICarServiceFactory
{
private readonly Dictionary<string, ICreateCars> _services
= new Dictionary<string, ICreateCars>(StringComparer.OrdinalIgnoreCase);
public CarServiceFactory(IServiceProvider serviceProvider)
{
_services.Add("ford", serviceProvider.GetService<FordFigoFactory>());
_services.Add("audi", serviceProvider.GetService<AudiQ7Factory>());
}
public ICreateCars Create(string input)
{
Console.WriteLine(input + " car is created.");
return _services.ContainsKey(input) ? _services[input] : _services["ford"];
}
}
public interface ICreateCars
{
Car CreateACar(string color);
}
public class FordFigoFactory : ICreateCars
{
public Car CreateACar(string color)
{
Console.WriteLine("FordFigo car is created with color:" + color);
return new Fordigo { Color = color};
}
}
public class AudiQ7Factory : ICreateCars
{
public Car CreateACar(string color)
{
Console.WriteLine("AudiQ7 car is created with color:" + color);
return new AudiQ7 { Color = color };
}
}
public abstract class Car
{
public string Model { get; set; }
public string Color { get; set; }
public string Company { get; set; }
}
public class Fordigo : Car
{
public Fordigo()
{
Model = "Figo";
Company = "Ford";
}
}
public class AudiQ7 : Car
{
public AudiQ7()
{
Model = "Audi";
Company = "Q7";
}
}
}
Explanation:
To understand better try to read the program from bottom to top. We have 3 sections:
Car (Car, Fordigo, AudiQ7)
CarFactory (ICreateCars, FordFigoFactory, AudiQ7Factory)
CarService (ICarServiceFactory, CarServiceFactory)
In this Dependency injection is registered as transient for Factory classes FordFigoFactory and AudiQ7Factory. And Singleton for CarServiceFactory.

Castle Windsor injecting controller with two instances of same interface

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(...);
}

Binding autofac with webapi using generic repository

I am trying to use autofac with a repository and I am trying to add a little generics to try reducing the amount of duplicate code I am writing.However I am going round in circles trying to get autofac to work for me
So I created a domainservice and interface that handles our the standard crud operations
public class DomainService<T>:IDomainService<T>
{
protected readonly IDomainService<T> Repository;
public DomainService(IDomainService<T> repository)
{
Repository = repository;
}
public IQueryable<T> GetQueryable()
{
return Repository.GetQueryable();
}
public virtual Task<T> Add(T entity)
{
return Repository.Add(entity);
}
Interface:
public interface IDomainService<T>
{
IQueryable<T> GetQueryable();
Task<T> Add(T entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
Task<T> GetById(int id);
Task<T> GetByUID(Guid id);
}
I am using my repo is nothing special
public class SkillRepository : DomainService<Skill>, ISkill
{
private DataContext _db = new DataContext();
private readonly ILogger _log = null;
public SkillRepository(IDomainService<Skill> repository, ILogger log) : base(repository)
{
_log = log;
}
}
Finally where I wire up autofac:
var builder = new ContainerBuilder();
// Register the Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register other dependencies.
builder.Register(c => new Logger()).As<ILogger>().InstancePerApiRequest();
builder.RegisterType<SkillRepository>()
.As<IDomainService<Skill>>()
.As<ISkill>()
.InstancePerRequest();
// Build the container.
var container = builder.Build();
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
My web api controller looks like
public class SkillsController : BaseController<Skill>
{
private readonly ISkill _skillRepository;
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
{
_skillRepository = skillRepository;
}
}
BaseController
public abstract class BaseController<TEntity> : ApiController
where TEntity : new()
{
protected readonly IDomainService<TEntity> DomainService;
protected BaseController(IDomainService<TEntity> domainService)
{
DomainService = domainService;
}
I get an exception:
"None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'Api.EndPoints.Skills.SkillsController' can be invoked with the
available services and parameters:\ \ Cannot resolve parameter
'Domain.Repository.SkillRepository skillRepository' of constructor
'Void .ctor(Domain.Repository.SkillRepository)'."
Is there something obvious that I am doing wrong?
It cannot resolve the dependency because it's looking for the concrete type but you never registered SkillsRepository as that. Now you could change the registration to register the concrete type but that wouldn't be the best approach.
A better approach is to register SkillsRepository as its interfaces:
builder.RegisterType<SkillRepository>()
.As<ISkillsRepository>()
.InstancePerRequest();
And define ISkillsRepository to inherit all the other interfaces like ISkill that you want.
public interface ISkillsRepository : ISkill, IDomainService<Skill> { }
Don't register objects as concrete types and don't depend on concrete types in constructors.
public SkillsController(ISkillRepository skillRepository) :
base(skillRepository) ...
If you use concrete types as dependencies you create classes that cannot be tested using mocking frameworks.
Your use of SkillRepository : DomainService<Skill>, ISkill is perplexing too. Why is it both a skill and a domain service for skills? Doesn't make much sense.
Exception clearly states:
Cannot resolve parameter 'Domain.Interfaces.ISkill skillRepository' of constructor 'Void .ctor(Domain.IDomainService`1[Model.Skill], Domain.Interfaces.ISkill)'.
You have only IDomainService registered. But no ISkill (the line is commented).
Also why does the ctor require 2 parameters? SkillRepository implements both IDomainService<Skill> and ISkill so you should be able to pass it along:
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
P.S.
I'd name it this way:
public class SkillRepository : ISkillRepository, IDomainService<Skill>
And I prefer everything to be either plural (SkillsControllers, SkillsRepository) or everything singular (SkillController, SkillRepository).
In my opinion you should first sort out names for your classes which is making it hard to understand the code itself. secondly your repository is implementing domain service interface and ISkill and things like that is adding more confusion. i am pretty sure if you organise your classes properly then you will find solution to your problem.
For instance ApiController should use domain service, domain service should use repository and repository should deal with enties.
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(string name){}
public void DeleteSkillById(int id){}
..... etc
}
public class Repository:IRepository
{
public T Get(int id){}
public IEnumerable<T>GetAll(){}
}
Then you need to bind your interfaces to concrete classed in ioc. things should work that way i am pretty sure.

How to use Simple injector, Repository and Context - code first

I'm trying to use Simple Injector to create my repository and use it in the Business logic layer ( also i want to use PerWebRequest method ) .
In the DAL layer i have :
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Delete(int id);
void Update(T entity);
T GetById(int Id);
IQueryable<T> All();
IEnumerable<T> Find(Func<T, bool> predicate);
}
and :
public class EFRepository<T> : IRepository<T>, IDisposable where T : class
{
#region Members
protected DbContext Context { get; set; }
protected DbSet<T> DbSet { get; set; }
#endregion
#region Constructors
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
Context = dbContext;
DbSet = Context.Set<T>();
}
and my context :
public class PASContext : DbContext, IDbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
public PASContext()
: base("PostAndSell")
{ }
}
As you can see EFRepository has only one constructor that takes one argument - this is because i want to use Simple Injector to create an instance of the context and pass it to the repository while it is created .
In the BLL i have a class ProductBLL and i want to get all products in that class (with some GetAll method) from the database and pass it, lets say to HomeController .
I really need someone to talk me through this .
I started by installing the right packages from the nuger (Simple Injector and Simple Injector ASP.NET Integration)
also in my global.asax.cs file, under Application_Start() function I`ve added :
var container = new SimpleInjector.Container();
container.RegisterPerWebRequest<IRepository<Product>, EFRepository<Product>>();
but where do i create the Context instance ? and how can i access it in the business layer ?
Since you will probably have many IReposotory<T> implementations (for Product, Customer, Employee, etc), it's better make a single open generic registration for IRepository<T> like this:
container.Register(typeof(IRepository<>), typeof(EFRepository<>), Lifestyle.Scoped);
Where the scoped lifestyle is defined as:
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
This registration ensures that Simple Injector will return a EFRepository<Product>, every time a IRepository<Product> is requested, an EFRepository<Customer> for IRepository<Customer>, and so on, and so on.
Since you want the same DbContext instance to be used over all repositories within the same request, you should also register the DbContext with the scoped Lifestyle:
container.Register<DbContext, PASContext>(Lifestyle.Scoped);
In the BLL i have a class ProductBLL and i want to get all products
from the database and pass it to, lets say HomeController
In that scenario, this ProductBLL seems like a useless abstraction to me. If all it does is passing data through, you can as easily let your HomeController depend on IRepository<Product> directly.

Categories