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.
Related
Please bear with me - this is a complicated question, and I've simplified it as much as I am able. (I'm using ASP.NET web API and AutoFac and omitted a bunch of configuration for brevity.)
My goal is to maximize the extent to which dependency-injection is handled by a DI framework, in a situation where not all dependencies of some objects can be known until runtime.
Our players are:
a CONTROLLER class that accepts web requests, the entry point to the app - the input includes repoName
a REPOSITORY RESOLVER class, a factory that resolves a repoName into a specific REPOSITORY. Here's its implementation:
public class RepositoryResolver : IRepositoryResolver
{
public IRepository Resolve(string repoName)
{
return new Repository(new Input { RepoName = repoName });
}
}
a REPOSITORY class (representing a DB or whatever). Here's its implementation:
public class Repository : IRepository
{
private readonly Input input; // proxy for connection string or other identifying information
public Repository (Input input)
{
this.input = input;
}
public string[] Get()
{
return new[] { "I", "am", "a", input.RepoName };
}
}
a BUSINESS LOGIC class that computes a result. The BUSINESS LOGIC class depends on a single repository; it knows nothing of multiple repositories or the repository resolver because it's not concerned with them. Here's its implementation:
public class BusinessLogic : IBusinessLogic
{
private readonly IRepository repository;
public BusinessLogic(IRepository repository)
{
this.repository = repository;
}
public string[] Compute()
{
return repository.Get();
}
}
Procedurally, what I'm trying to accomplish (in this stripped-down toy example) is very straightforward. Here's an example implementation of the controller:
Proposed Answer #1 - Pure DI (no container)
public class PureDIController : ApiController
{
public ProceduralValuesController() { }
public IEnumerable<string> Get(string repoName)
{
IRepositoryResolver repoSource = new RepositoryResolver();
IRepository repo = repoSource.Resolve(repoName);
IBusinessLogic businessLogic = new BusinessLogic(repo);
return businessLogic.Compute();
}
}
...and this works, but obviously I'm not using a DI container here. When using pure DI like this, changes to one player tend to have ripple effects beyond its immediate collaborators and potentially through many layers (not represented here); I feel like moving this composition logic into a DI container will reduce a lot of that type of refactoring. That's the value proposition of this question.
However, when I try to rewrite this class using dependency-injection, I encounter a problem: the BUSINESS LOGIC depends on the REPOSITORY, so it cannot be resolved by a pre-created DI container. Hence, I cannot resolve the hand-waving comment here:
public class DIValuesController : ApiController
{
private readonly IRepositoryResolver repoSource;
private readonly IBusinessLogic businessLogic;
public DIValuesController(
IRepositoryResolver repoSource,
IBusinessLogic businessLogic)
{
this.repoSource = repoSource;
this.businessLogic = businessLogic;
}
public IEnumerable<string> Get(string repoName)
{
var repo = repoSource.Resolve(repoName);
/* ...handwaving to integrate repo into businessLogic... */
return businessLogic.Compute();
}
}
...because IBusinessLogic cannot be resolved at the time the controller is instantiated.
I've developed several possible solutions, and I will add them as potential answers. However, I don't like any of them, hence the post. ¯_(ツ)_/¯ Please surprise me with something I haven't thought of yet!
Yet another possibility - pass IBusinessLogic to Controller not as an instance, but as a factory (i.e. Func<string, IBusinessLogic>) and in Methode Compute Fall factory with repoName.
See, for example:
https://autofaccn.readthedocs.io/en/latest/advanced/delegate-factories.html
Answer #2 - Pass parameters as necessary
This solution abandons the original premise that we can fruitfully convert a method parameter into a constructor parameter. Instead, it assumes that the repoName (or some equivalent differentiator) will need to be passed into any function that requires that information. Here's one possible example implementation of the controller (note that BusinessLogic now requires an additional parameter):
public class ParameterPassingController : ApiController
{
private readonly IBusinessLogic businessLogic;
public ParameterPassingController(
IBusinessLogic businessLogic)
{
this.businessLogic = businessLogic;
}
public IEnumerable<string> Get(string repoName)
{
return businessLogic.Compute(repoName);
}
}
And here's the new implementation of BusinessLogic:
public class BusinessLogic : IBusinessLogic
{
private readonly IRepositoryResolver repositoryResolver;
public BusinessLogic(IRepository repositoryResolver)
{
this.repositoryResolver = repositoryResolver;
}
public string[] Compute(string repoName)
{
var repo = repositoryResolver.Resolve(repoName);
return repo.Get();
}
}
This solution feels very awkward because it modifies the BusinessLogic class to depend on a less direct object than it did before. A class's dependencies should be determined by the class, not by the needs of the caller. The BusinessLogic class was better the way it was before, and any solution that causes us to make it more complicated is probably not a good one.
Answer #3 - Introduce additional resolvers
This solution adds a BUSINESS LOGIC RESOLVER, using the same pattern as the REPOSITORY RESOLVER. (Factory pattern?)
public class BusinessLogicResolverController : ApiController
{
private readonly IRepositoryResolver repoSource;
private readonly IBusinessLogicResolver businessLogicSource;
public BusinessLogicResolverController(
IRepositoryResolver repoSource,
IBusinessLogicResolver businessLogicSource)
{
this.repoSource = repoSource;
this.businessLogicSource = businessLogicSource;
}
public IEnumerable<string> Get(string repoName)
{
var repo = repoSource.Resolve(repoName);
var businessLogic = businessLogicSource.Resolve(repo);
return businessLogic.Compute();
}
}
The thing I don't like about this is that if there are many classes that depend on a single IRepository (and in my non-trivial example, there are many), I need to create a Resolver for each of them. That also complicates other things that DI containers can help with like decorator application and stuff.
Answer #4 - Introduce temporal coupling
This solution replaces the registered implementation of IRepository with a class that also implements IRepositoryManager, allowing it to be pointed at the appropriate repo at runtime. Here's what the controller looks like now:
public class TemporallyCoupledController : ApiController
{
private readonly IRepositoryManager repoManager;
private readonly IBusinessLogic businessLogic;
public TemporallyCoupledController(
IRepositoryManager repoManager,
IBusinessLogic businessLogic)
{
this.repoManager = repoManager;
this.businessLogic = businessLogic;
}
public IEnumerable<string> Get(string repoName)
{
repoManager.Set(repoName);
return businessLogic.Compute();
}
}
...and here's the implementation of IRepositoryManager:
public class RepositoryManager : IRepositoryManager, IRepository
{
private readonly IRepositoryResolver resolver;
private IRepository repo = null;
public RepositoryManager(IRepositoryResolver resolver)
{
this.resolver = resolver;
}
void IRepositoryManager.Set(string repoName)
{
this.repo = resolver.Resolve(repoName);
}
string[] IRepository.Get()
{
if (repo == null)
throw new InvalidOperationException($"{nameof(IRepositoryManager.Set)} must be called first.");
else
return repo.Get();
}
}
This solution certainly allows the controller to stay small, but in my experience, temporal coupling almost always hurts more than it helps. Also, it's unclear that these two lines in the controller have anything to do with each other:
repoManager.Set(repoName);
return businessLogic.Compute();
...but obviously they do. So this is a pretty bad solution.
Answer #5 - Inject the parameter-based dependency inside the controller
This solution makes the controller part of the composition root, rather than having it be resolved by dependency injection. (The line where the built container is retrieved could be done in other ways, but that's not the important part - the main idea is that we need to access its BeginLifetimeScope method directly after we have the input parameters.)
public class SelfAwareDIController : ApiController
{
public SelfAwareDIController() { }
public IEnumerable<string> Get(string repoName)
{
var container = (AutofacWebApiDependencyResolver)GlobalConfiguration.Configuration.DependencyResolver;
using (var scope = container.Container.BeginLifetimeScope(builder =>
builder.RegisterInstance(new Input { RepoName = repoName }).AsSelf()))
{
var businessLogic = scope.Resolve<IBusinessLogic>();
return businessLogic.Compute();
}
}
}
This solution avoids temporal coupling (since businessLogic cannot exist outside the lifetime scope where it can be resolved). It also allows us to remove the REPOSITORY RESOLVER; I was already uncomfortable with REPOSITORY RESOLVER because it's an expansion of the Composition Root that interferes with the DI container's centralized handling of object creation. A downside is that it moves some of the container-related code into the controller rather than keeping it all in the service configuration. (Again, in a non-trivial example there may be many controllers that need to implement similar logic.) It also prevents the controller itself from being instantiated by the DI container (which you can do with AutoFac.WebApi2 package). Still, because it restricts the knowledge of this new context to the controller (and removes the necessity of having a factory class), this is probably the least objectionable of the solutions that I've identified.
So I have windsor set up and all of my services registered. I have a class that requires these services in the ctor, but this class isn't registered with windsor as it does not have an interface and I don't want to give it one for the sake of dependency resolution. What I'm really interested in, is having windsor resolve and inject my registered dependencies and hand me back an initialized class -- basically a factory.
The problem that I'm running into is that windsor throws because the dependent class has not been registered:
void Main()
{
var container = new WindsorContainer();
container.Register(Component
.For<ITestInterface>()
.ImplementedBy<TestImpl>()
.LifestyleTransient());
var c = container.Resolve<TestClass>(); // throws because TestClass isn't registered
c.Run();
}
public class TestClass
{
private ITestInterface _d;
public TestClass(ITestInterface d)
{
_d = d;
}
public void Run()
{
_d.Do();
}
}
public interface ITestInterface
{
void Do();
}
public class TestImpl : ITestInterface
{
public void Do()
{
Console.WriteLine("done");
}
}
What I don't want to end up doing, is something like this:
var dependency1 = container.Resolve<ITestInterface>();
var c = new TestClass(dependency1);
c.Run();
Because now we're in service locator territory. But more importantly, classes that have several dependencies...well that could get tedious.
How can I get windsor to have the desired factory effect? Or is this even possible with Windsor? I recall this being possble with Ninject.
So the popular response seems to be "Just register the component" which I really don't like at all because for such a simple use case, I could end up with a config class with hundreds of unnecessary registrations. That's kind of silly. So in the meanwhile, until I discover some built in functionality for this, I've create a cheesy extension that should land me somewhere in the middle. This extension simply takes the type, registers it for you and then tries to resolve it. That way, it's leveraging Windsor's own ctor resolution logic:
public static class WindsorExtentions
{
public static T Construct<T>(this IWindsorContainer container)
where T : class
{
if (!container.Kernel.HasComponent(typeof(T)))
container.Register(Component.For<T>());
var instance = container.Resolve<T>();
return instance;
}
}
What I would really like to do is register it, resolve it, then unregister it, but it appears that the RemoveComponent method has been removed in 3.0. This should be fine in the meanwhile. It obviously isn't all-inclusive with use cases, but when you have loads of proxy classes that have several required dependencies to be injected, I think this helps.
Usage:
var myClassWithDependencies = myContainer.Construct<MyClassWithDependencies>();
public class MyClassWithDependencies
{
public MyClassWithDependencies(
IFacebookClient facebookClient,
IGooglePlusClient googlePlusClient,
ITwitterClient twitterClient,
ISalesforceClient salesforceClient,
IReportRepository reportRepo,
IUserRepository userRepo)
{
}
}
I'm brand new to using Simple Injector although I have been using Ninject for a long time, so I am comfortable with DI in general. One thing that attracted me to want to use Simple Injector was the ease of use of Decorators.
I have been able to successfully use decorators with Simple Injector in all normal cases where the dependencies are resolved when the service is requested. However, I am having a hard time figuring out if there is a way to get my decorators applied in a case when the service must be constructed using a runtime value.
In Ninject, I could pass a ConstructorArgument to the kernel.Get<IService> request that could be inherited down the chain of N decorators all the way to the "real" implementing class. I cannot figure out a way to replicate that using Simple Injector.
I have put some very basic code below to illustrate. What I would want to do in the real world would be to pass an IMyClassFactory instance into other classes in my application. Those other classes could then use it to create IMyClass instances using the IRuntimeValue they would provide. The IMyClass instance they got from the IMyClassFactory would be decorated automatically by the registered decorators.
I know I could manually apply my decorator(s) in my IMyClassFactory or any Func<IMyClass> I could come up with, but I would like it to "just work".
I keep going around and around trying to abstract out the MyClass construction, but I can't figure out how to get it to resolve with the IRuntimeValue constructor argument and be decorated.
Am I overlooking an obvious solution?
using System;
using SimpleInjector;
using SimpleInjector.Extensions;
public class MyApp
{
[STAThread]
public static void Main()
{
var container = new Container();
container.Register<IMyClassFactory, MyClassFactory>();
container.RegisterDecorator(typeof (IMyClass), typeof (MyClassDecorator));
container.Register<Func<IRuntimeValue, IMyClass>>(
() => r => container.GetInstance<IMyClassFactory>().Create(r));
container.Register<IMyClass>(() => ?????)); // Don't know what to do
container.GetInstance<IMyClass>(); // Expect to get decorated class
}
}
public interface IRuntimeValue
{
}
public interface IMyClass
{
IRuntimeValue RuntimeValue { get; }
}
public interface IMyClassFactory
{
IMyClass Create(IRuntimeValue runtimeValue);
}
public class MyClassFactory : IMyClassFactory
{
public IMyClass Create(IRuntimeValue runtimeValue)
{
return new MyClass(runtimeValue);
}
}
public class MyClass : IMyClass
{
private readonly IRuntimeValue _runtimeValue;
public MyClass(IRuntimeValue runtimeValue)
{
_runtimeValue = runtimeValue;
}
public IRuntimeValue RuntimeValue
{
get
{
return _runtimeValue;
}
}
}
public class MyClassDecorator : IMyClass
{
private readonly IMyClass _inner;
public MyClassDecorator(IMyClass inner)
{
_inner = inner;
}
public IRuntimeValue RuntimeValue
{
get
{
return _inner.RuntimeValue;
}
}
}
Edit 1:
Ok, thanks to Steven for the great answer. It has given me a couple of ideas.
Maybe to make it a little more concrete though (although not my situation, more "classic"). Say I have an ICustomer that I create at runtime by reading a DB or deserializing from disk or something. So I guess that would be considered a "newable" to quote one of the articles Steven linked. I would like to create an instance of ICustomerViewModel so I can display and manipulate my ICustomer. My concrete CustomerViewModel class takes in an ICustomer in its constructor along with another dependency that can be resolved by the container.
So I have an ICustomerViewModelFactory that has a .Create(ICustomer customer) method defined which returns ICustomerViewModel. I could always get this working before I asked this question because in my implementation of ICustomerViewModelFactory I could do this (factory implemented in composition root):
return new CustomerViewModel(customer, container.GetInstance<IDependency>());
My issue was that I wanted my ICustomerViewModel to be decorated by the container and newing it up bypassed that. Now I know how to get around this limitation.
So I guess my follow-up question is: Is my design wrong in the first place? I really feel like the ICustomer should be passed into the constructor of CustomerViewModel because that demonstrates intent that it is required, gets validated, etc. I don't want to add it after the fact.
Simple Injector explicitly lacks support for passing on runtime values through the GetInstance method. Reason for this is that runtime values should not be used when the object graph is constructed. In other words, the constructors of your injectables should not depend on runtime values. There are several problems with doing that. First of all, your injectables might need to live much longer than those runtime values do. But perhaps more importantly, you want to be able to verify and diagnose your container's configuration and that becomes much more troublesome when you start using runtime values in the object graphs.
So in general there are two solutions for this. Either you pass on the runtime value through the method call graph or you create a 'contextual' service that can supply this runtime value when requested.
Passing on the runtime value through the call graph is especially a valid solution when you practice architectures like this and this where you pass on messages through your system or when the runtime value can be an obvious part of the service's contract. In that case it is easy to pass on the runtime value with the message or the method and this runtime value will also pass through any decorator on the way through.
In your case this would mean that the factory creates the IMyService without passing in the IRuntimeValue and your code passes this value on to the IMyService using the method(s) it specifies:
var service = _myServiceFactory.Create();
service.DoYourThing(runtimeValue);
Passing through the runtime value through the call graph however is not always a good solution. Especially when this runtime value should not be part of the contract of the message that is sent. This especially holds for contextual information use as information about the current logged in user, the current system time, etc. You don't want to pass this information through; you just want it to be available. We don't want this, because this would give an extra burden to the consumers of passing the right value every time, while they probably shouldn't even be able to change this information (take the user in who's context the request is executed for instance).
In that case you should define service that can be injected and allows retrieving this context. For instance:
public interface IUserContext {
User CurrentUser { get; }
}
public interface ITimeProvider {
DateTime Now { get; }
}
In these cases the current user and the current time aren't injected directly into a constructor, but instead these services are. The component that needs to access the current user can simply call _userContext.CurrentUser and this will be done after the object is constructed (read: not inside the constructor). Thus: in a lazy fashion.
This does mean however that the IRuntimeValue must be set somewhere before MyClass gets invoked. This probably means you need to set it inside the factory. Here's an example:
var container = new Container();
var context = new RuntimeValueContext();
container.RegisterSingle<RuntimeValueContext>(context);
container.Register<IMyClassFactory, MyClassFactory>();
container.RegisterDecorator(typeof(IMyClass), typeof(MyClassDecorator));
container.Register<IMyClass, MyClass>();
public class RuntimeValueContext {
private ThreadLocal<IRuntimeValue> _runtime;
public IRuntimeValue RuntimeValue {
get { return _runtime.Value; }
set { _runtime.Value = value; }
}
}
public class MyClassFactory : IMyClassFactory {
private readonly Container _container;
private readonly RuntimeValueContext context;
public MyClassFactory(Container container, RuntimeValueContext context) {
_container = container;
_context = context;
}
public IMyClass Create(IRuntimeValue runtimeValue) {
var instance = _container.GetInstance<IMyClass>();
_context.RuntimeValue = runtimeValue;
return instance;
}
}
public class MyClass : IMyClass {
private readonly RuntimeValueContext _context;
public MyClass(RuntimeValueContext context) {
_context = context;
}
public IRuntimeValue RuntimeValue { get { return _context.Value; } }
}
You can also let the MyClass accept the IRuntimeValue and make the following registration:
container.Register<IRuntimeValue>(() => context.Value);
But the disallows verifying the object graph, since Simple Injector will ensure that registrations never return null, but context.Value will be null by default. So another option is to do the following:
container.Register<IMyClass>(() => new MyClass(context.Value));
This allows the IMyClass registration to be verified, but will during verification still create a new MyClass instance that is injected with a null value. If you have a guard clause in the MyClass constructor, this will fail. This registration however disallows MyClass to be auto-wired by the container. Auto-wiring that class can come in handy when you've got more dependencies to inject into MyClass for instance.
I have a class (MyFacade) that I injected parameter(s) with Ninject:
class MyFacade
{
IDemoInterface demo;
public MyFacade(IDemoInterface demo)
{
this.demo = demo;
}
public void MyMethod()
{
Console.WriteLine(demo.GetInfo());
}
}
Of course, I have to setup the Ninject to inject the appropiate implementation of my parameter (IDemoInterface)
I know, I can instantiate MyFacade object by doing kernel.Get<MyFacade>(); without setting anything else. Currently my facade doesn't have an interface (because it is my only implementation, maybe I will add its interface for standard proposes)
if I want to make this facade singlenton, I know two ways: create a empty constructor and pass a parameter by doing this kernel.Get<IDemoInterface>(); or by setup Ninject like: kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
The second one look a better approach, but do you know any other way to setup it in a singleton way?
When setting up your bindings, you need to bind your dependencies. It is always better to setup your dependencies in your bindings, as opposed to doing a kernel.Get<T>() in a constructor. You are using IOC, so leverage the framework you are using to do the injection for you.
In your second example binding, what you are missing is binding in your IDemoInterface. Your bindings should look like this:
//bind the dependency to the implementation.
kernel.Bind<IDemoInterface>().To<DemoInterface>();
//since you bound your dependency, ninject should now have
// all the dependencies required to instantiate your `MyFacade` object.
kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
If you do not want the container to manage the lifecycle of your singleton by using InSingletonScope(), but still wants it to get injected, I can think of 2 ways to go about it. Choose which one suits better to your needs. Consider the following ISingleton (name your interface) implementation:
public class ConcreteSingleton : ISingleton
{
private static readonly Lazy<ConcreteSingleton> _instance = new Lazy<ConcreteSingleton>(() => new ConcreteSingleton());
private ConcreteSingleton() { }
public static ConcreteSingleton Instance
{
get
{
return _instance.Value;
}
}
}
Alter the singleton class to have a GetInstance(...) method
In this method (my preferred approach), you won't be calling kernel.Inject(instance) each time, only for the first time the singleton is initialized. Adding the following method to your ConcreteSingleton class:
public static ConcreteSingleton GetInstance(IKernel kernelForInjection)
{
if (_instance.IsValueCreated == false)
{
kernelForInjection.Inject(_instance.Value);
}
return _instance.Value;
}
And using this binding:
kernel.Bind<ISingleton>().ToMethod(c => ConcreteSingleton.GetInstance(c.Kernel));
Will achieve the desired behavior of not having a public constructor but enabling your facade to be efficiently injected.
Perform injection each time the ISingleton instance is requested
If by any reason you are not allowed to modify your ConcreteSingleton: This approach will wrap the singleton creation in a provider to efficiently inject the instance only for the first time it is created. It is important to note that the provider itself must be registered as a singleton.
internal class ConcreteSingletonProvider : Provider<ISingleton>
{
public IKernel Kernel { get; set; }
//Just a wrapper
private readonly Lazy<ISingleton> _lazy = new Lazy<ISingleton>(() => ConcreteSingleton.Instance);
public ConcreteSingletonProvider(IKernel kernel)
{
Kernel = kernel;
}
protected override ISingleton CreateInstance(IContext context)
{
if (_lazy.IsValueCreated == false)
{
Kernel.Inject(ConcreteSingleton.Instance);
}
return _lazy.Value;
}
}
And your bindings should be like this:
kernel.Bind<ISingleton>().ToProvider<ConcreteSingletonProvider>();
kernel.Bind<ConcreteSingletonProvider>().ToSelf().InSingletonScope();
This gist has a complete working sample for the above approach.
Hope that helps!
How do you create simple Dependency Resolver, with out using any built in or library such as Autofac, Ninject, etc.
This was my interview question.
I wrote this simple code and they said it does not look good. Its like very hard coded idea.
public interface IRepository { }
interface IDataProvider
{
List<string> GetData();
}
public class SQLDataProvider : IDataProvider
{
private readonly IRepository _repository { get; set; }
public SQLDataProvider(IRepository repository)
{
_repository = repository;
}
public List<string> GetData()
{
return new List<string> { "" };
}
}
public class MockDataProvider : IDataProvider
{
public List<string> GetData()
{
return new List<string> { "" };
}
}
class Program
{
static void Main(string[] args)
{
string targetClass = "SQLDataProvider";
//Here i need to supply IRepository instance too
IDataProvider dataProvider =
(IDataProvider)Activator.CreateInstance(typeof(IDataProvider), targetClass);
}
}
What better code i do and supply other object instance for constructor parameter?
DI Containers are complex libraries. Building them takes years and maintaining them decades. But to demonstrate their working, you can write a simplistic implementations in just a few lines of code.
At its core a DI Container would typically wrap a dictionary with System.Type as its key and, the value would be some object that allows you to create new instances of that type. When you write a simplistic implementation System.Func<object> would do. Here is an example that contains several Register methods, both a generic and non-generic GetInstance method and allows Auto-Wiring:
public class Container
{
private readonly Dictionary<Type, Func<object>> regs = new();
public void Register<TService, TImpl>() where TImpl : TService =>
regs.Add(typeof(TService), () => this.GetInstance(typeof(TImpl)));
public void Register<TService>(Func<TService> factory) =>
regs.Add(typeof(TService), () => factory());
public void RegisterInstance<TService>(TService instance) =>
regs.Add(typeof(TService), () => instance);
public void RegisterSingleton<TService>(Func<TService> factory)
{
var lazy = new Lazy<TService>(factory);
Register(() => lazy.Value);
}
public object GetInstance(Type type)
{
if (regs.TryGetValue(type, out Func<object> fac)) return fac();
else if (!type.IsAbstract) return this.CreateInstance(type);
throw new InvalidOperationException("No registration for " + type);
}
private object CreateInstance(Type implementationType)
{
var ctor = implementationType.GetConstructors().Single();
var paramTypes = ctor.GetParameters().Select(p => p.ParameterType);
var dependencies = paramTypes.Select(GetInstance).ToArray();
return Activator.CreateInstance(implementationType, dependencies);
}
}
You can use it as follows:
var container = new Container();
container.RegisterInstance<ILogger>(new FileLogger("c:\\logs\\log.txt"));
// SqlUserRepository depends on ILogger
container.Register<IUserRepository, SqlUserRepository>();
// HomeController depends on IUserRepository
// Concrete instances don't need to be resolved
container.GetInstance(typeof(HomeController));
WARNING: You should never use such naive and simplistic implementation as given above. It lacks many important features that mature DI libraries give you, yet gives no advantage over using Pure DI (i.e. hand wiring object graphs). You lose compile-time support, without getting anything back.
When your application is small, you should start with Pure DI and once your application and your DI configuration grow to the point that maintaining you Composition Root becomes cumbersome, you could consider switching to one of the established DI libraries.
Here are some of the features that this naive implementation lacks compared to the established libraries:
Auto-Registration: The ability to apply Convention over Configuration by registering a set of types with in single line, instead of having to register each type manually.
Interception: the ability to apply decorators or interceptors for a range of types
Generics: Mapping open-generic abstractions to open generic implementations
Integration: using the library with common application platforms (such as ASP.NET MVC, Web API, .NET Core, etc)
Lifetime Management: The ability to registering types with custom lifestyles (e.g. Scoped or Per Request).
Error handling: Detection of misconfiguration such as cyclic dependencies. This simplistic implementation throws a stack overflow exception.
Verification: Features or tools for verifying the correctness of the configuration (to compensate the loss of compile-time support) and diagnosing common configuration mistakes.
Performance: Building large object graphs will be slow using this simplistic implementation (e.g. causes a lot of GC pressure due to the amount of produced garbage).
These features and abilities allow you to keep your DI configuration maintainable when using a DI Container.
It's already a few years old, but Ayende once wrote a blog post about this:
Building an IoC container in 15 lines of code
But this is only the very simplest possible implementation.
Ayende himself stated in his next post that the existing IoC containers can do much more stuff than just returning class instances - and this is where it gets complicated.
As "Trust me - I'm a Doctor" already said in his comment: implementing a complete IoC container is everything but trivial.