Is it the best practice to inject ILifetimeScope to the constructor? - c#

I'm using static function Resolve() in ILifetimeScope instance injected from constructor.
private readonly ILifetimeScope _container;
public MyService(ILifetimeScope container)
{
_container = container;
}
private void Save()
{
using (var scope = _container.BeginLifetimeScope())
{
var rdb = scope.Resolve<IDatabase>();
bool result = rdb.Save(name:"newAccount"); // I can't Assert the result.
}
}
In this case, I got a problem when I made a unit test.
Since ILifetimeScope's Resolve() function is a static function, it couldn't be mocked and couldn't be asserted.
As far as I understood, It means two classes are tightly coupled.
However, if ILifetimeScope is not injected, too many classes will have to be injected.
In this situation, I would like to ask the following questions.
I would like to ask if it is best practice to use Resolve() function which is from injected ILifetimeScope instance. if is not true, all the dependencies should be injected by constructor?
public MyService(ILogger logger, IDatabase database, IAccountServer accountService /*more and more*/)
{
}
if there is the way I can mock the Reslove() function, Please let me know.
Thank you in advance.

Related

How to resolve circular dependencies inside of the service layer [duplicate]

This question already has answers here:
Dependency Injection Architectural Design - Service classes circular references
(4 answers)
Closed 3 years ago.
I know that others already had this very same issue, but I cannot find any statisfying solution, so I'm asking here for other ideas.
My business logic is contained in a service layer like that:
public class RoomService : IRoomService
{
private readonly IRoomRepository _roomRepository;
private readonly ICourseService _courseService;
public RoomService(IRoomRepository roomRepository, ICourseService courseService)
{
_roomRepository = roomRepository ?? throw new ArgumentNullException(nameof(roomRepository));
_courseService = courseService ?? throw new ArgumentNullException(nameof(courseService));
}
public Task DeleteRoomAsync(string id)
{
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
}
public class CourseService : ICourseService
{
private readonly ICourseRepository _courseRepository;
private readonly IRoomService _roomService;
public CourseService(ICourseRepository courseRepository, IRoomService roomService)
{
_courseRepository = courseRepository ?? throw new ArgumentNullException(nameof(courseRepository));
_roomService = roomService ?? throw new ArgumentNullException(nameof(roomService));
}
public Task GetAllCoursesInBuilding(string buildingId)
{
// Query all rooms in building (requires IRoomService)
// Return all courses for these rooms
}
}
This is just an example. There might be workarounds to avoid that the services depend on each other in this case, but I had multiple other situations in the past, where there wasn't any clean workaround.
As you can see, these two services depend on each other and dependency injection will fail because of the circular dependency.
Now I can imagine two ways to resolve this:
Solution 1
I could resolve the service-dependencies inside of the service methods that require them instead of injecting the service dependencies into the service constructor:
public class RoomService : IRoomService
{
private readonly IRoomRepository _roomRepository;
private readonly IServiceProvider _serviceProvider;
public RoomService(IRoomRepository roomRepository, IServiceProvider serviceProvider)
{
_roomRepository = roomRepository ?? throw new ArgumentNullException(nameof(roomRepository));
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public Task DeleteRoomAsync(string id)
{
ICourseService courseService = _serviceProvider.GetRequiredService<ICourseService>();
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
}
Problem: This makes unit testing harder because I need to inject a mocked IServiceProvider that is able to resolve my ICourseService into the class constructor. Also it's not very clear when writing the unit tests, which services are required by each service method because that's completely implementation dependant.
Solution 2
The service method could require that the ICourseService is passed in from the controller as a method parameter:
public Task DeleteRoomAsync(ICourseService courseService, string id)
{
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
Problem: Now my controller needs to know about an implementation detail of the service method: DeleteRoomAsync requires an ICourseService object to do it's work.
I think that's not very clean because the requirements of DeleteRoomAsync might change in future, but the method signature should not.
Can you think of any alternative, cleaner solutions?
If your framework supports it, you can provide your injected dependencies as a Lazy<T> which defers resolution and allows you to have circular dependencies.
Here's what those service classes might look like:
class FooService : IFooService
{
protected Lazy<IBarService> _bar;
public FooService(Lazy<IBarService> bar)
{
_bar = bar;
}
public void DoSomething(bool callOtherService)
{
Console.WriteLine("Hello world. I am Foo.");
if (callOtherService)
{
_bar.Value.DoSomethingElse(false);
}
}
}
class BarService : IBarService
{
protected Lazy<IFooService> _foo;
public BarService(Lazy<IFooService> foo)
{
_foo = foo;
}
public void DoSomethingElse(bool callOtherService)
{
Console.WriteLine("Hello world. I am Bar.");
if (callOtherService)
{
_foo.Value.DoSomething(false);
}
}
}
The code that registers them does not require modification (at least not with Autofac):
public static IContainer CompositionRoot()
{
var builder = new ContainerBuilder();
builder.RegisterType<FooService>().As<IFooService>().SingleInstance();
builder.RegisterType<BarService>().As<IBarService>().SingleInstance();
builder.RegisterType<Application>().SingleInstance();
return builder.Build();
}
See a working example on DotNetFiddle.
If your framework does not support lazy injection like this, you can probably do the exact same thing using a factory (or any other pattern that defers resolution).
See also this answer which helped me come up with this solution.
The best solution is to avoid circular dependencies, of course, but it you're truly stuck, you can work around the issue by using property injection and RegisterInstance<T>(T t) (or its equivalent, if you're not using Autofac).
For example, if you have a FooService class and a BarService class that depend on each other, you can do this:
public static IContainer CompositionRoot()
{
var foo = new FooService();
var bar = new BarService();
foo.Bar = bar;
bar.Foo = foo;
var builder = new ContainerBuilder();
builder.RegisterInstance<IFooService>( foo );
builder.RegisterInstance<IBarService>( bar );
builder.RegisterType<Application>().SingleInstance();
return builder.Build();
}
This instantiates both services without their dependencies, and then sets them to each other afterward. By the time they are registered with the IoC container, their dependencies are completely set up.
See my Fiddle for a working example.
In provided examples, I would re-consider if you really have inter-service dependencies in those kind of situations:
Do you need logic contained in ICourseService in your RoomService implementation, or do you only need information from certain courses?
I would say that the latter one, so your real dependency could be ICourseRepository
with a method ICourseRepository.FindByRoom(Room room).
Do you need logic contained in IRoomService in your CourseService implementation, or do you only need existing rooms?
In this case, IRoomRepository could be enough.
However, it isn't always that easy and sometimes you really require logic implemented in Service layer, (validations, etc.). Trying to extract that behavior to shared classes rather than duplicating it or creating circular dependencies as mentioned can be preferrable in those scenarios.

Autofac initializing the container in a constructor

I have read multiple articles about whether or not to do resource intensive operations in the constructor. Some of them say if it doesn't affect SRP or Testability then it is fine. I want an opinion on best practices for this scenario.
I am following the Composition Root principle mentioned here in my ASP.Net WebApi2 project and my controllers have got their dependent objects injected. Instead of injecting just a few dependencies, I want to inject the entire container and have any of the dependencies available. I have this class design where I am setting up the container property in the constructor. I dont know if this qualifies as bad practice.
public class AppContainer : IAppContainer
{
private readonly ContainerBuilder _builder ;
private IContainer _container ;
public AppContainer ()
{
_builder = new ContainerBuilder();
_builder.RegisterAssemblyModules(_assembly);
_container = _builder.Build();
}
public ContainerBuilder ContainerBuilder
{
get { return _builder; }
}
public IContainer Container
{
get { return _container;}
}
}
Is it bad design to call the .Build() in the constructor as done above? I want to do this so that the AppContainer's properties are initialized at the time of creation of the instance and not waiting for some method to be called for the properties to hold value.
Now in my controller instead of having something like this
public class HomeController : ApiController
{
private readonly IBusiness _bus;
public HomeController(IBusiness bus)
{
_bus = bus;
}
I can have something like this and expose the container directly. This way my controller's constructor definitions don't change everytime I needed a new dependency injected in.
public class HomeController : ApiController
{
private readonly IAppContainer _container;
public HomeController (IAppContainer container)
{
_container = container;
}
Is it bad design to call the .Build() in the constructor as done above?
In general, it is not recommended that you do a lot in constructors.
Also, I don't recommend that you use the AppContainer class at all. You are simply wrapping the container with the AppContainer class and using it as a service locator which is an anti-pattern.
Your classes should declare their dependencies explicitly in the constructor as in your first example of HomeController.
If you design your classes with the SOLID principles in mind, then your classes would be small and would not require a lot of dependencies so you almost wouldn't have to add new dependencies.
Please note that having too many dependencies (> ~3) might be an indication that you are violating the Single Responsibility Principle and is considered a code smell.

Simple Injector - inject container property

I want to inject Container property via SimpleInjector. I didn't find any functionality of SimpleInjector for that.
Then I wanted to register self container to itself, but Container has no interface.
I want this functionality because I don't to transfer Container object via constructor - because why if I can use auto inject of register objects.
My usage idea:
var container = new Container();
container.Options.AutowirePropertiesWithAttribute<InjectableProperty>();
container.Register<ISomething, Something>(Lifestyle.Singleton);
ISomething:
public interface ISomething
{
void SomeMethod();
}
Something class:
public class Something : ISomething
{
public void SomeMethod()
{
var environment = _container.GetInstance<IEnvironment>();
environment.DoSomething();
}
[InjectableProperty] // - maybe it is not possible (I don't know it)
Container Container {get;set;}
}
Do you have any idea to achieve that?
Thank you very much.
Prevent having your application code depend upon the container. The only place in your application that should know about the existence of your DI library is the Composition Root (the place where you register all your dependencies).
Instead of letting each class call back into the container (which is called the Service Locator anti-pattern), prefer using Dependency Injection. With Dependency Injection you inject dependencies instead of asking for them.
So you can rewrite your class to the following:
public class Something : ISomething
{
private readonly IEnvironment environment;
public Something (IEnvironment environment)
{
this.environment = environment;
}
public void SomeMethod()
{
this.environment.DoSomething();
}
}
Also, prevent doing any logic in your constructors besides storing the incoming dependencies. This allows you to compose object graphs with confidence.
In some cases however, it can still be useful to inject the Container into another class. For instance when creating a factory class that is located inside the Composition Root. In that case you can still use constructor injection, like this:
// Defined in an application layer
public interface IMyFactory
{
IMyService CreateService();
}
// Defined inside the Composition Root
public class MyFactory : IMyFactory
{
private readonly Container container;
public MyFactory(Containter container)
{
this.container = container;
}
public IMyService CreateService(ServiceType type)
{
return type == ServiceType.A
? this.container.GetInstance<MyServiceA>()
: this.container.GetInstance<MyServiceB>();
}
}
If Simple Injector detects a Container constructor argument, it will inject itself into the constructor automatically.

Ninject: injecting inside extension methods

I have an extension class for a Product object.
Is there any way of injecting the service classes i need without passing them as method parameters?
public static class ProductExtensionMethods
{
public static void CalculatePrice(this Product product,
ICalculateProductPriceService _calculatePriceService,
IUnitOfWork _unitOfWork)
{
// Can I inject the unitOfWork and Service without
// passing them as parameters?
product.Price = _calculatePriceService.Calculate();
_unitOfWork.Commit();
}
}
You can't do this with any DI container afaik because although you can define a constructor on a static class, that constructor must be parameterless.
The only way I could see this working for you would be to either
define CalculatePrice on instances of Product but the instance function simply passes through the call to the static method. Inject the dependencies into the instance via constructor and pass them via the static call within the instance call.
Create a "helper" class that does the same thing (e.g ProductPriceHelper) and implement a Setup or Initialise method on it taking the dependencies, but you still will not* be able to have DI auto-inject for you - you'll have to do it manually somewhere in your composition rot (i.e wherever you currently do all your Ninject binding).
Secret door #3: I would be inclined to rearrange how your price calcuation works; I would humbly suggest that your ICalculateProductPriceService should have a method that accepts a Product instance and performs its magic therein. The ICalculateProductPriceService dependency is then injected into the Product during construction and you call a method Product.GetPrice() which invokes ICalculateProductPriceService.Calculate(this)...if you can't or won't inject the service during ctor (e.g if it is an EF entity, etc) then you can make it a required param dependency on GetPrice.
I realise that having said this someone will no doubt come up with a technically excellent workaround to allow this, but it will always be a hack...
It seems as if you are implementing use cases inside extension methods. I see no benifits for doing this over creating normal classes. So instead of using an extension method, simply make this method non-static, wrap it in an non-static class, and inject the dependencies through the constructor.
This could look like this:
public class CalculateProductPriceUseCase
{
private ICalculateProductPriceService _calculatePriceService;
private IUnitOfWork _unitOfWork;
public CalculateProductPriceUseCase(
ICalculateProductPriceService calculatePriceService,
IUnitOfWork unitOfWork)
{
_calculatePriceService = _calculatePriceService;
_unitOfWork = unitOfWork;
}
public void Handle(Product product)
{
product.Price = _calculatePriceService.Calculate();
_unitOfWork.Commit();
}
}
What still bothers me about this solution however is the Commit call. Why should the use case itself have to call commit. That seems like an infrastructure thing to me and it is easy to forget to implement this. Especially since the class doens't create the unitOfWork itself, but gets it from the outside.
Instead you can wrap this use case in a decorator that does this for you, but... if you do that, you'll need to add a proper abstraction so you can wrap all your use cases in such decorator. It could look like this:
public class CalculateProductPrice
{
public int ProductId { get; set; }
}
public class CalculateProductPriceUseCaseHandler
: IUseCase<CalculateProductPrice>
{
private ICalculateProductPriceService _calculatePriceService;
private IUnitOfWork _unitOfWork;
public CalculateProductPriceUseCaseHandler(
ICalculateProductPriceService calculatePriceService,
IUnitOfWork unitOfWork)
{
_calculatePriceService = _calculatePriceService;
_unitOfWork = unitOfWork;
}
public void Handle(CalculateProductPrice useCase)
{
var product = _unitOfWork.Products.GetById(useCase.ProductId);
product.Price = _calculatePriceService.Calculate();
}
}
Consumers can now depend on an IUseCase<CalculateProductPrice> and you can give them either an CalculateProductPriceUseCaseHandler instance, or wrap that instance in a decorator. Here's an example of such decorator:
public class TransactionUseCaseDecorator<T> : IUseCase<T>
{
private IUnitOfWork _unitOfWork;
private IUseCase<T> _decoratedInstance;
public TransactionUseCaseDecorator(IUnitOfWork unitOfWork,
IUseCase<T> decoratedInstance)
{
_unitOfWork = unitOfWork;
_decoratedInstance = decoratedInstance;
}
public void Handle(T useCase)
{
// Example: start a new transaction scope
// (or sql transaction or what ever)
using (new TransactionScope())
{
_decoratedInstance.Handle(useCase);
// Commit the unit of work.
_unitOfWork.Commit();
}
}
}
Now you have one single generic decorator that can be wrapped around any IUseCase<T> implementation.

StructureMap, ObjectFactory and the IContainer

I'm working with StructureMap for my IoC needs.
To make things pleasantly testable, I'm passing IContainer instances around wherever possible, usually as constructor parameters. As a convenience, I'd like to be able to fall back to using ObjectFactory for a parameterless constructor.
The simplest way (I thought) to do this would be to simply get the IContainer the ObjectFactory class wraps and pass that to the other constructor. Unfortunately, I can't find anywhere this instance is publicly exposed.
The question is:
Is there a way to get the IContainer within ObjectFactory so I can handle it as simply as a user-supplied instance?
Alternatively, is there a way to duplicate the configuration of the ObjectFactory into a new Container instance?
Example:
I would like to be able to do the following:
public class MyClass
{
public MyClass()
{
Container = ... // The ObjectFactory container instance.
}
public MyClass(IContainer container)
{
Container = container;
}
public IContainer Container { get; private set; }
}
ObjectFactory exposes a Container property which gives you the IContainer you are looking for.
Anytime you need an IContainer (which should not be often) you can always take a dependency on it in your class ctor.
public class INeedAContainer
{
private readonly IContainer _container;
public INeedAContainer(IContainer container)
{
_container = container;
}
// do stuff
}
I do not think there is a way to clone an IContainer. There is a container.GetNestedContainer() method which allows you to keep your transients the same for the lifetime of the nested container. Nested containers are often used within a "using" statement and are very handy for controlling the state of things like database transaction boundaries.

Categories

Resources