How to get DbContext in nested methods using Simple Injector - c#

I have a doubt since I'm new to Dependency Injection and IoC.
I have a domain layer (with business logic) and a data layer. We do not implement repositories, we use EF Core directly.
It is a Class Library project, we use it in a ASP.NET CCore Web API, WinForms, and inside another framework.
The idea is to use the same context inside a scope.
The problem is that I'm not being able to get the same context in the nested method execution, I'm sure it is because I did not understand the concept completely, can you guys give me a help on that?
Example:
public class MyTest
{
public void TestContainer()
{
var parentContext = MyContainer.Container.GetInstance<MyContext>();
TestParentAndChildContext(parentContext);
}
private void TestParentAndChildContext(MyContext parentContext)
{
var childContext = MyContainer.Container.GetInstance<MyContext>();
Assert.AreEqual(parentContext, childContext);
}
}
public class MyContainer
{
public static Container Container
{
get { return container ?? (container = RegisterAndVerifyContainer()); }
}
private static Container RegisterAndVerifyContainer()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.Register<DbContext, MyContext>(Lifestyle.Scoped);
container.Verify();
return container;
}
}

In Simple Injector you register an implementation by its abstraction. In your case you registed an MyContext by its DbContext base type. From this point on Simple Injector will know that it will need to construct a MyContext in case someone asks for a DbContext. This is the whole purpose of
Program to an interface, not an implementation
In your case however, although you do register the MyContext by its abstraction, you request a new instance of MyContext directly, instead of requesting it through its abstraction. This causes Simple Injector to look for the MyContext in its list of registered abstractions. Since there is no registration for MyContext (there is for DbContext though, but that's a totally different type what Simple Injector is concerned), Simple Injector will try to add the missing registration. This succeeds because MyContext is concrete and has single resolvable constructor, while you are using Simple Injector v4.x.
By default the older versions of Simple Injector will resolve unregistered concrete types as Transient. This default changed in v5, where it won't create any unregistered concrete type by default.
So MyContext is resolved as transient when requested directly. You can solve this by changing your test to the following:
public void TestContainer()
{
using (MyContainer.Container.BeginExecutionContextScope()) {
var parentContext = MyContainer.Container.GetInstance<DbContext>();
TestParentAndChildContext(parentContext);
}
}
private void TestParentAndChildContext(MyContext parentContext)
{
var childContext = MyContainer.Container.GetInstance<DbContext>();
Assert.AreEqual(parentContext, childContext);
}
Do note that Simple Injector usually detects these kinds of mistakes. In case you register MyContext by its DbContext base type, but inject MyContext directly in a constructor of a type, Simple Injector will throw a Short-Circuited Dependency error when calling Verify().
The reason you didn't get warned about this, is because you've called Verify() before the resolve action (you should typically not call GetInstance from within your application; instead you should build all object graphs up front). But when you'd call Verify (again) after resolving MyContext you would see the exception popping up:
[TestMethod]
public void TestContainer()
{
var container = MyContainer.Container.GetInstance<DbContext>();
var parentContext = container.GetInstance<MyContext>();
var childContext = container.GetInstance<MyContext>();
// This call will fail
container.Verify();
}

Related

How to instantiate an object with a reference to another object that depends on DI ASP.NET core 2.0?

I have a controller's constructor in which I want to instantiate an object that gets access to the repository via dependency injection.
like this:
ContactController.cs: I get an error because I don't pass an IContactRepository
private ContactOperationsFacade contactOperator;
ContactController(){
contactOperator = new ContactOperationsFacade(//I want to use DI here);
}
ContactOperationsFacade.cs:
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
How can I instantiate this ContactOperationsFacade object in the controller's constructor still using DI for the repository?
In asp.net core you can do DI chaining as long as scopes allow it. So if A depends on B and the controller wants A you just add both A and B to the di container (ConfigureServices part of your code) and the container will figure it out.
Read more here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
ContactController should follow The Explicit Dependencies Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Also classes should depend on abstractions and not coupled to concretions.
So assuming something like
public class ContactOperationsFacade: IContactOperationsFacade { //<-Note interface/contract
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
//...
}
The controller should depend on the abstraction that the facade is derived from
public class ContactController: Controller {
private readonly IContactOperationsFacade contactOperator;
public ContactController(IContactOperationsFacade contactOperator){
this.contactOperator = contactOperator;
}
//...
}
And assumes that all the interfaces and implementations are registered with the DI container.
services.AddScoped<IContactOperationsFacade, ContactOperationsFacade>();
once all dependencies are registered the service provider should resolve them when activating the controller.

Unity dependency not resolving in task

I'm unsure of how to fix my current situation. I'm attempting to create a task:
public class whatever
{
[Dependency]
public IReportingBL ReportingBL { get; set; }
private whatever()
{
...task factory creation, etc.
}
private readonly static Lazy<whatever> _instance = new Lazy<whatever>(() => new whatever());
public static whatever Instance { get { return _instance.Value; }
public Task GetStuff()
{
return _taskFactory.StartNew(() =>
{
return ReportingBL.Method1;
});
}
}
ReportingBL doesn't get resolved. If I create a new instance of ReportingBL inside the thread then the layers below it don't get resolved.
How do I go about getting unity to work in this situation?
You are applying the Singleton Design Pattern. This is a pattern that is frown upon and considered an anti-pattern by some. In Dependency Injection terminology the Singleton pattern can be considered an Ambient Context, which is a pattern that should hardly ever be used in the context of Dependency Injection.
The Singleton Design Pattern does not work well with Dependency Injection, because:
With Dependency Injection it is the application's Composition Root who is in control of creating instances and caching them; not the instance itself.
Having consumers depend on the public Instance field, causes the consumers to violate the Dependency Inversion Principle and disallows the instance from being replaced, mocked, decorated or intercepted. This hinders maintainability and testability of your application.
Further more, in your code I don't see any calls to the Unity DI framework. Please remember that a DI container is not a magical tool that will allow classes to be initialized 'by them selves'. In your code you new up whatever directly; Unity is not involved in this. Unity (or any DI library for that matter) can only auto-wire the object if it is in control of it. In other words, you will have to call container.Resolve<whatever>() for Unity to build up your instance.
Although you could call container.Resoolve from within the Lazy<T> factory delegate, this forces the class to take a dependency on the container itself, which is commonly referred to as the Service Locator anti-pattern.
Instead, I propose the following changes to your design:
Use constructor injection instead of property injection. Property injection leads to Temporal Coupling.
Make the Composition Root and the container responsible for wiring up object graphs.
Stay away from the Singleton design pattern; use the container's Singleton Lifestyle instead.
This results in the following code:
public interface IWhatever
{
Task GetStuff();
}
public class Whatever : IWhatever
{
private readonly IReportingBL reportingBL;
public whatever(IReportingBL reportingBL) {
this.reportingBL = reportingBL;
}
public Task GetStuff() {
return _taskFactory.StartNew(() => {
return ReportingBL.Method1;
});
}
}
// Some consumer of whatever
public class MyController : Controller
{
private readonly IWhatever whatever;
public MyController(IWhatever whatever) {
this.whatever = whatever;
}
public ActionResult Index() {
return View(this.whatever.GetStuff());
}
}
In your composition root, you can configure the class as follows:
var container = new UnityContainer();
container.RegisterType<IReportingBL, ReportingBL>(
new ContainerControlledLifetimeManager());
container.RegisterType<IWhatever, Whatever>(
new ContainerControlledLifetimeManager());
var controller = container.Resolve<MyController>();
controller.Index();

Best practice for Ninject to get different implementations based on top level project

I am just starting to learn Dependency Injection and I am stuck here.
My project has a WCF DataService over an Entity Framework DbContext.
public class MyDataService : DataService<MyDbContext>
{
protected override MyDbContext CreateDataSource()
{
// I want to use dependency injection for this
return new MyDbContext();
}
}
The class is either
a) IIS hosted, so I don't have any control
b) for integration tests, created with var host = new DataServiceHost(type, new Uri[] { });
both use different contstructors for MyDbContext
So basically to inject the Context with this
protected override MyDbContext CreateDataSource()
{
INinjectModule module = ???; // -
IKernel kernel = new StandardKernel(module);
return kernel.Get<MyDbContext>();
}
So the question is, what is best practice in this situation?
Should I:
a) Create a Module in a Class Library that both main projects and the service use
b) Create a public static Variable inside the DataService project that holds the Ninject module.
c) Create a public static Variable inside the DataService project that holds the Ninject kernel
d) Something else.
I would prefer something like
protected override MyDbContext CreateDataSource()
{
DefaultKernel.Get<MyDbContext>();
}
Firstly, you should have a Composition Root. That is, a single place where your Kernel is created (not in every single function).
Secondly, you don't need a NinjectModule here.. you're asking Ninject to create an instance of a concrete object (which in almost all circumstances.. defeats the purpose).
What you should create, is a separate NinjectModule pass it into the constructor of the Kernel.. something like this:
interface IContext {
}
class MyDbContext : DbContext, IContext {
}
class YourModule : NinjectModule {
protected override void Bind() {
Bind<IContext>().To<MyDbContext>();
}
}
// In your composition root somewhere
var kernel = new StandardKernel(new NinjectModule[] { new YourModule() });
// in your createdatasource method
kernel.Get<IContext>();
This will get you started. Normally, your composition root is what drives injection of objects throughout your application, thereby eliminating the need to pass the Kernel around (which you will have to do in your current setup).
The hard thing to understand when starting out with DI/IoC is that it is the container's job to create your entire dependency graph. Therefore, if you setup the following bindings:
IContract1 -> ConcreteObject1
IContract2 -> ConcreteObject2
IContract3 -> ConcreteObject3
..and have the following setup:
class ConcreteObject1 : IContract1 {
public ConcreteObject1(IContract2 contract3) {
}
}
class ConcreteObject2 : IContract2 {
public ConcreteObject2(IContract3 contract3) {
}
}
If you ask your container for a concrete implementation of IContract1 (which will be ConcreteObject1), then it will create it.... BUT: ConcreteObject1 requires a concrete implementation of IContract2 in the constructor. So the container says "Wait, I know how to create this".. and passes in an instance of ConcreteObject2. Again, it says "wait, ConcreteObject2 wants a concrete implementation of IContract3.. again, it goes and fetches one.
Hopefully that helps.

Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?

In my bootstrapper:
namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
}
in my controller's code:
ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
hovering on mUnityContainer I see ISettingsManager is mapped to SettingsManager
but then I get the error:
Exception is: InvalidOperationException - The current type, is an
interface and cannot be constructed. Are you missing a type mapping?
I have also tried
ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
but no use
Just for others (like me) who might have faced the above error. The solution in simple terms.
You might have missed to register your Interface and class (which implements that inteface) registration in your code.
e.g if the error is
"The current type, xyznamespace. Imyinterfacename, is an interface and cannot be constructed. Are you missing a type mapping?"
Then you must register the class which implements the Imyinterfacename in the UnityConfig class in the Register method. using code like below
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:
public class HomeController: Controller
{
private readonly ISettingsManager settingsManager;
public HomeController(ISettingsManager settingsManager)
{
this.settingsManager = settingsManager;
}
public ActionResult Index()
{
// you could use the this.settingsManager here
}
}
As you can see in this example the controller doesn't know anything about the container. And that's how it should be.
All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.
As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.
In my case, I was getting this error despite registering an existing instance for the interface in question.
Turned out, it was because I was using Unity in WebForms by way of the Unity.WebForms Nuget package, and I had specified a Hierarchical Lifetime manager for the dependency I was providing an instance for, yet a Transient lifetime manager for a subsequent type that depended on the previous type - not usually an issue - but with Unity.WebForms, the lifetime managers work a little differently... your injected types seem to require a Hierarchical lifetime manager, but a new container is still created for every web request (because of the architecture of web forms I guess) as explained excellently in this post.
Anyway, I resolved it by simply not specifying a lifetime manager for the types/instances when registering them.
i.e.
container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
becomes
container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
So that IMapper can be resolved successfully here:
public class UserContext : BaseContext, IUserContext
{
public UserContext(IMapper _mapper) : base(_mapper)
{
}
...
}
In my case, I have used 2 different context with Unitofwork and Ioc container so i see this problem insistanting while service layer try to make inject second repository to DI. The reason is that exist module has containing other module instance and container supposed to gettng a call from not constractured new repository.. i write here for whome in my shooes
May be You are not registering the Controllers.
Try below code:
Step 1.
Write your own controller factory class
ControllerFactory :DefaultControllerFactory by implementing defaultcontrollerfactory
in models folder
public class ControllerFactory :DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(string.Format(
"Type requested is not a controller: {0}",
controllerType.Name),
"controllerType");
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch
{
return null;
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
}
Step 2:Regigster it in BootStrap:
inBuildUnityContainer method
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
//RegisterTypes(container);
container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>();
MvcUnityContainer.Container = container;
return container;
}
Step 3:
In Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
And you are done
I had this problem, and the cause was that I had not added the Microsoft.Owin.Host.SystemWeb NuGet package to my project. Although the code in my startup class was correct, it was not being executed.
So if you're trying to solve this problem, put a breakpoint in the code where you do the Unity registrations. If you don't hit it, your dependency injection isn't going to work.
Below code will be helpful for you
public static IUnityContainer Initialise(IUnityContainer container = null)
{
if (container == null)
{
container = new UnityContainer();
}
container.RegisterType<ISettingsManager, SettingsManager>();
container.Resolve<SettingsManager>();
container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
return container;
}

C# Dependency Injection and the Strategy Pattern

I'm using Munq as the DI container in a MVC3 project. I have a service layer that retrieves a DTO from a repository. Depending on a property in that DTO I need to use one of two strategies to perform calculations on the DTO. I can register a named type in the container e.g.
Container.Register<ICalculation>("Type1", c => new Type1Calculation);
Container.Register<ICalculation>("Type2", c => new Type2Calculation);
Then I can refer directly to the container when trying to instantiate the appropriate strategy e.g.
var calc = Container.Resolve<ICalculation>(dto.ServiceType);
But this leaves me with a dependency on the container itself with the associated coupling and testing issues. What do I need to pass into the service constructor that would allow me to get the correct calculation but without the dependency on the container? Should I pass in a factory instead so the dependency is in the factory and not in the service class?
Not sure about Munq, but Autofac allows you to pass around Funcs, so that you can skip all factories altogether:
public class Foo
{
public Foo(Func<string, IBar> barFactory) { }
}
Check if Munq allows for such behavior.
Otherwise -- yes, you'll have to resort to hand-written factories to provide yet another level of indirection.
I've added the Munq solution to this. First the factory which includes the IDependencyResolver interface to allow the factory to use the container to resolve dependencies in the factory method:
public class CalculationFactory
{
private readonly IDependencyResolver _resolver;
public CalculationFactory(IDependencyResolver resolver)
{
ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
_resolver = resolver;
}
public static ICalculation CreateCalculator(int serviceType)
{
switch (serviceType)
{
case 1: return _resolver.Resolve<ICalculation>("Type1");
case 2: return _resolver.Resolve<ICalculation>("Type2");
default: return _resolver.Resolve<ICalculation>("InvalidType");
}
}
}
Then in Global.asax.cs register the appropriate interfaces/classes, passing in the container to the factory. So now I can set up my tests and the only extra dependency is IDependencyResolver within the factory:
ioc.Register(c => new CalculationFactory(c));
ioc.Register<ICalculation>("Type1", c => c.Resolve<Type1Calculation>());
ioc.Register<ICalculation>("Type2", c => c.Resolve<Type2Calculation>());
ioc.Register<ICalculation>("InvalidType", c => c.Resolve<InvalidCalculation>());

Categories