Using Autofac, suppose I have a PersonRepository and an EventRepository class, which both depend on a IDataService service... I use both of the repository classes in an Mvc Controller action (for example - might as well be some MvvM WPF application) like
public class Mycontroller : controller
{
public Mycontroller(PersonRepository personRepo, EventRepository eventRepo) {...}
...
public ActionResult Index(){ ... I use the repository classes in here ...}
}
public class PersonRepository
{
public PersonRepository(IDataService service){...}
}
public class EventRepository
{
public PersonRepository(IDataService service){...}
}
I want to make sure, when using the repository classes and injecting them with a IDataService implementation, that both of the repository classes receive the same instance of the IDataService service...
How can I do that?
It depends on the lifetime of the IDataService.
Do you want to keep reusing the same one over and over again? Then it's basically a singleton, and you must configure Autofac to treat it as one:
builder.RegisterType<IDataService>().As<MyDataService>().SingleInstance();
But if you're running in MVC and want to reuse the same instance only during the lifetime of the HTTP request, you configure Autofac like so:
builder.RegisterType<IDataService>().As<MyDataService>().HttpRequestScoped();
Call the .SingleInstance() method when registering the component. (assuming fluent registration)
Try implementing the IComponentLifetime with your rules of reusing and register the services using your lifetime.
Related
I am developing a web API in .NET Core with multiple DataContexts(DbContext). I have used repository pattern to handle DB calls. The Repository class accepts a DbContext as a generic type.
public class Repository<T> : IRepository where T : DbContext
{
public Repository(T context) : base(context)
{
}
}
This Repository class injects to service classes as IRepository from the Startup. I want to connect with 2 databases. So I`m using 2 DataContext classes and passed them in to repository class in the startup.
Here is my Startup class,
services.AddTransient<DataContext1>(x => new DataContext1(Configuration.GetConnectionString("Database1")));
services.AddTransient<IRepository, Repository<DataContext1>>();
services.AddTransient<DataContext2>(x => new DataContext2(Configuration.GetConnectionString("Database2")));
services.AddTransient<IRepository, Repository<DataContext2>>();
When I request IRepository it always injects the Repository class with the last DataContext(DataContext2). What is the best way to solve this problem without affecting to the API performance(Memory / CPU).
Here is my Service class,
private readonly IRepository _repository;
public BookService(IRepository repository)
{
_repository = repository;
}
I think you should at least create one repository interface for each type of database in order of the dependency injection system can handle it.
Inject a factory class for the repositories instead of an instance of the repositories themselves. Implement the factory methods to suit your needs.
I have setup the dependency injection in startup.cs say: IAction. In controller, I can inject the service as a parameter in the constructor. But what if my normal class in Business Layer for example, How do that service be injected.
In Microsoft documentation, it is a bad design if do something like the image below:
Is there a better way? If I tried passed these service from controller to other layers, this will not give good result as well.
You should be able to pass the same dependencies through the constructors of the classes in your business layer just like you pass them through the constructors of your controllers in your Web API layer or MVC layer.
Something like this:
public class UsersService
{
private readonly IUsersRepository usersRepository;
public UsersService(IUsersRepository usersRepository)
{
this.usersRepository = usersRepository;
}
public async Task<User> GetUser(int userId)
{
return await usersRepository.GetByIdAsync(userId);
}
}
In ASP.NET Core MVC all classes that implement Controller will be automatically resolved and added to the MVC pipeline. These controllers can also be injected into the DI container using services.AddMvc().AddControllersAsServices();
I also have a controller that also implements a specific interface, which I can also add to the DI container: services.AddSingleton<IMyInterface, MyImpl>();
public class MyImpl : Controller, IMyInterface { }
However, becase this controller also implements Controller it has already been added in AddControllersAsServices() so adding it to the DI container one more time causes there to be two instances of this class.
The reason for this design is that I will have multiple implementations of IMyInterface and later need to decide which one to use, but each implementation will also need to be a controller in order to provide certain API endpoints (each controller will provide different endpoints, so there will be no conflicts there).
How can I ensure that only one instance of my class is instantiated, and how can I then get all implementations of IMyInterface?
As much as Im concerned Controller class is instantiated on each request, so even if you specify something like this (Ninject style):
services.Bind<IMyInterface, MyController>().To<MyController>().InSingletonScope();
It will be very bad. I mean, Controller is statefull, and you just mix everything up and breaking it's internal context.
What you might do is decorate through controller, instead of managing its lifetime yourself:
public class MyImpl : IMyInterface
{
}
public class MyController : Controller
{
private readonly IMyInterface _inner; //delegate implementation to this one.
public MyController(IMyInterface inner)
{
_inner = inner;
}
}
And injection:
services.Bind<IMyInterface>().To<MyImpl>().InSingletonScope();//this is your logic.
sercices.Bind<MyController>().ToSomethingWhatever();//this line is managed by ASP .NET, mentioned this only to show the idea
You might need remove the MyImpl inheriting from Controller class. Also you need to consider MyImpl as sevice rather than Controller.
Another option is that this can be achieved with IoC container like Autofac or Ninject or Castle Windsor. When using with Autofac it will be something like the below
Add the Autofac, Autofac ASP.Net MVC4 Integration using NuGet Package
Open GLobal.asax.cs
Make following changes in the Application_Start().
3a. Comment out the below code as
//WebApiConfig.Register(GlobalConfiguration.Configuration);
3b. Create a new method RegisterAutofac(), call this as the first method call inside Application_Start()
3c. Below with the sample implementation for RegisterAutofac() method
private void RegisterAutofac()
{
var builder = new Autofac.ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterSource(new ViewRegistrationSource());
// The object to be injected in constructor etc.
builder.RegisterType<MyImpl>().As<IMyInterface>().SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
I am sure there are answers on here to my question, though I just don't either quite understand what I'm looking for or what I'm reading... Also, not 100% sure DI is what I should be using in this case.
I am attempting to use Unity for my DI. I am injecting dependency into ASP.Net Web API Controllers. And so far so good.
I am injecting Services into my controllers that the controller will require. For example, in one of my controllers I have:
private TransactionService _transactionService;
public TransactionsController(TransactionService transactionService)
{
_transactionService = transactionService;
}
In this case I am injecting an instance of TransactionService into the controller. This is all working.
My WebApiConfig.cs contains the following, which as i understand it actually performs the injection:
var container = new UnityContainer();
container.RegisterType<ServiceBase>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
I can show you my UnityResolver if needed.
Now the part I'm struggling with...
My services all inherit from an Abstract class ServiceBase - in its simplest for it looks like this:
public abstract class ServiceBase : IDisposable
{
internal Account _account;
public ServiceBase(){}
}
What I would like to do is create the Account during my injection process and pass it in somehow so that my injected services don't need to deal with instansiating the account.
The moment I try adding any constructors to my services to accept an Account I receive the message to ensure my controllers have a parameterless constructor.
So.. how do i set up my DI so that I can inject services into my controllers and also inject a pre-instantiated instance of Account into my services?
Update
I forgot to mention (sorry Wiktor) - I would like to NOT use Attributes if possible. It seems strange in my mind that we can use DI to unhook dependency and then go and put a bunch of dependent attributes everywhere. I quite possibly just don't understand the DI concept correctly, though this doesn't seem right to me
That should be simple, just make the additional property public and add the dependency attribute on it.
[Dependency]
public Account _account { get; set; }
Unity should be able to inject the attribute and you can even register the Account class in an ordinary way (for example with an injection factory).
I hope this would give some idea for you.
Create an interface for service base and declare Acccount as public property.
Interface for your service:
you can also inherit other interfaces.
public interface ITransactionService : IDisposable
{
IAccount Account{get;set;}
}
Implement it in your class:
public class TransactionService : ITransactionService{
private IAccount _account;
public IAccount Account
{
get
{if(_account==null)_account=new Account(); return _account;}
set
{_account=value;}
}
}
Now use the constructor at API controller as shown below:
private ITransactionService _transactionService;
public TransactionsController(ITransactionService transactionService)
{
_transactionService = transactionService;
}
Unity resolver:
var container = new UnityContainer();
container.RegisterType<ITransactionService,TransactionService>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
So using in this way where property injection and constructor injection used for reducing tightly coupled dependency.
It will be very easy for mocking the interface for unit testing.
You may also create an interface for Account class, so that it could be easy for mocking based on your use.
In case you don't want to use attributes, which I totally agree with, the best approach is to have ServiceBase accept the account parameter, like:
public abstract class ServiceBase {
private Account _account;
public ServiceBase(Account account) {
this._account = account;
}
}
You will have to declare the same constructor on your derived service as well TransactionService. When the controller is instantiated, Unity will correctly create the instance of Account class first and then pass it on to your TransactionService object via constructor injection. And you should register Account object using a life time manager to scope it to singleton.
Hope this helps.
I have a layered application with the following projects:
DAL (using EntityFramework with repositories)
DAL.Model (contains the entities, and is referenced by all the others)
Services
UI (in wpf)
The base repository looks like this:
public abstract class RepositoryBase<T> where T : class
{
private readonly MyContext context;
private readonly IDbSet<T> dbSet;
protected RepositoryBase(MyContext dataContext)
{
context = dataContext;
dbSet = context.Set<T>();
}
protected MyContext Context
{
get { return context; }
}
**And a series of virtual methods for Add, Delete, etc.
}
All repositories extend this one, such as:
public class MarketRepository : RepositoryBase<Market>
{
public MarketRepository(MyContext dataContext) : base(dataContext)
{
}
public IEnumerable<Market> GetAllMarkets()
{
return this.Context.Markets.ToList<Market>();
}
}
The services look like this:
public class MarketService
{
IMarketRepository _marketRepository;
public MarketService(IMarketRepository marketRepository)
{
_marketRepository = marketRepository;
}
public IEnumerable<Market> GetAllMarkets()
{
return _marketRepository.GetAllMarkets();
}
}
What I would like to achieve is that the UI layer would only have a reference to the Services layer, the Services layer only with the DAL layer (and all of them to Model, where the entities live) using DI (right now I'm using Unity).
The problem is, in my container in the UI I only want to do this
unity.RegisterType<IMarketService, MarketService>();
and not have to do it as well for the repositories, because then the UI layer would have a dependency on the DAL layer.
I thought about adding a parameterless constructor to the Service classes, like:
public MarketService() : this(new MarketRepository(*What would I put here?)) { }
but then I'm loosing the abstraction that the interface gives, and also I don't know what to do with the MyContext that the repository needs as a parameter; if I pass a new one, then I need to reference the DAL.
Should I change my repositories to create a new MyContext in the constructor, rather than getting it as a parameter?
How can I refactor my architecture to make it work properly and with minimal dependencies?
Well, I belive it is up to the bootstrapper to configure dependencies, in the higher level of the application. As it is usually the UI project, if it needs to reference other assemblies, so be it. If you do not like your UI project managing that, than create a bootstrapper project responsable for getting your app running and separete your UI classes in another one.
Your IoC container should support Dependency Injection using a string from an external configuration file. This way you are not hardcoding the mapping. Structuremap does this quite well, so I am sure other IoCs will.
Adding external dependenices as a parameter when creating an instance is the way to go.
I think you should make yourself more familiar with the different ways to configure Unity, so that the dependencies are resolved.
Could you elaborate why you are creating a repository when using a dependency injection framework?
When configuring DI, you should follow the same pattern - UI bootstrapper initializes Services, Services initialize DAL. (With autofac or ninject you could achiece this using modules. With unity you should emulate modules).
In pseudocode something like
//ui
void UILayer.ConfigureUnity(unity)
{
ServiceLayer.ConfigureUnity(unity)
}
//services
void ServiceLayer.ConfigureUnity(unity)
{
DAL.ConfigureUnity(unity)
unity.RegisterType<IMarketService, MarketService>();
}
//dal
void DAL.ConfigureUnity(unity)
{
unity.RegisterType<IMarketRepository, MarketRespository>();
unity.RegisterType<MyContext, MyContext>(); //not sure exact syntax - just register type for 'new Type()' activator.
}