I am new with the dependency injection pattern. I'm a little confused about few things.
Scenario:
I have a class library project called 'MailCore'. This project has interfaces and classes that perform all email sending stuff.
I have an MVC project called 'The site'. It uses the 'MailCore' project to send email. I have Unity in this project and the UnityContainer is registered and things are working fine.
I also have another class library library project called 'SiteRepo'. Sometimes, to perform some specific tasks, I have to send email from this project. Therefore the 'MailCore' project is referenced in this project, too.
Problem:
I have installed Unity from NuGet in the 'SiteRepo' project and it doesn't seem to create any UnityConfig in this class library project.
How would I register a UnityContainer here?
Code:
TheSite:
Public class JobController : Controller
{
private readonly IEmailBuilder mailBuilder;
public JobController(IEmailBuilder mailBuilder)
{
this.mailBuilder = mailBuilder;
}
public ActionResult Create(....)
{
JobRepo j = new JobRepo();
j.Create(....);
}
}
UnityConfig (this is in the web app 'The Site'):
public static class UnityConfig
{
public static void RegisterComponents()
{
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>();
container.RegisterType<IEmailBuilder, EmailBuilder>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
SiteRepo:
Public class JobRepo()
{
Public bool Create(...)
{
//some other code to create a job....
//have to send email using MailCore !! The problem area in concern..
}
}
If you must use a DI Container like Unity (instead of Pure DI), you should install it into your Composition Root, which is 'The site'.
From there, you can reference the library projects and configure your container.
Related
I'm running into a strange issue using dependency injection, adding in a Singleton for a type that comes from an outside assembly. This is using the Azure Function framework, but I'm not sure if that has anything to do with it or if this would repro with ASP.NET Core as well. My actual "real world" implementation is far, far too complicated to outline here, but I've managed to come up with a minimal repro.
BugRepro.dll (This is a Azure Function project)
This has two files.
Test.cs:
public class Test
{
private readonly AppConfig config;
public Test(AppConfig config)
{
this.config = config;
}
[FunctionName("Test")]
public async Task<IActionResult> RunAsync([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
{
return new OkObjectResult(config.SampleSetting);
}
}
Startup.cs:
namespace BugRepro
{
public class AppConfig
{
public string SampleSetting { get; set; } = "Test";
}
public static class Startup
{
public static void Configure(IServiceCollection services)
{
services.AddSingleton(new AppConfig());
}
}
}
This assembly has a reference to TestDll.dll.
TestDll.dll (This is a normal .NET Core library)
Startup.cs:
[assembly: FunctionsStartup(typeof(TestDll.Startup))]
namespace TestDll
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var asm = Assembly.LoadFile(Path.Combine(builder.GetContext().ApplicationRootPath, #"bin\BugRepro.dll"));
var type = asm.GetType("BugRepro.Startup");
var method = type.GetMethod("Configure");
method.Invoke(null, new object[] {builder.Services});
}
}
}
When the Azure Function runs, the TestDll.Startup.Configure method is automatically called by the framework. This method loads the other assembly, BugRepro.dll using reflection and calls the BugRepro.Startup.Configure static method, passing the IServiceCollection.
The BugRepro.Startup.Configure static method adds a single instance of AppConfig to the service collection. I can verify the instance has successfully been added to the service collection, and stepping all the way into the code, the right ServiceDescriptor and everything has been created. Everything appears perfect.
However, when I call the /Test endpoint, I get the error:
[2021-02-04T06:39:10.502Z] Executed 'Test' (Failed, Id=22cfb587-3ba9-401f-b0a5-8688aed7bc9d, Duration=386ms)
[2021-02-04T06:39:10.506Z] Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'BugRepro.AppConfig' while attempting to activate 'BugRepro.Test'.
Basically, it acts like the Singleton has never been registered and it cannot resolve that type.
Ways to fix:
So, if I move the AppConfig class from the BugRepro.dll to TestDll.dll (basically the AppConfig type is in the same DLL as my FunctionsStartup class), the code works as expected.
Another way to fix it is to use an interface, which is defined in TestDll:
public interface IConfig
{
}
Then make AppConfig implement that interface, then register the Singleton using its interface:
services.AddSingleton<IConfig>(new AppConfig());
However, then I have to inject IConfig into the Test constructor rather than AppConfig which I do not want to do.
My Question
Is there a way to register a Singleton for a type that lives in an external assembly? To me, this seems like a bug in the .NET Core DI framework. Thanks!
This problem is caused by your use of Assembly.LoadFile. The LoadFile method can cause the same assembly to be loaded twice in such way that the framework sees this as a totally different assembly, with different types.
The solution is to use Asssembly.Load instead:
var assembly = Assembly.Load(AssemblyName.GetAssemblyName("c:\..."));
See for instance this related topic (for Simple Injector, but the problem is identical) for more information.
I am working on new web api project and using Unity.WebAPI as my DI. I have other projects which uses Microsoft.Practices.Unity as DI and resolving dependencies. I need to use objects from those objects in my web api project. When I try to register their dependencies, I am not able to convert Microsoft.Practices.Unity.IUnityContainer to Unity.WebApi.UnityContainer. I googled and could not achieve the output. Please see my below code reference:
Global.asax.cs
protected void Application_Start()
{
Bootstrapper.Initialise();
UnityConfig.RegisterComponents();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
// Other stuffs here
}
Bootstrapper.cs
public class Bootstrapper
{
public static void Initialise()
{
DependencyResolver.SetResolver(new UnityDependencyResolver(CreateContainer()));
}
public static Unity.IUnityContainer CreateContainer()
{
Microsoft.Practices.Unity.IUnityContainer container = RegisterMyDependencies();
return (Unity.IUnityContainer)container;
// suspicious cast: there is no type in the solution which is inherited from both 'Microsoft.Practices.Unity.IUnityContainer'
// and 'Unity.UnityContainer'
}
}
So, my controller is not resolving the dependencies. I understand that somewhere I am not making a communication between two libraries. I am new to this unity DI and not sure on how to resolve this issue. I tried using Unity package, it did not work as for web api project, we need to use Unity.WebApi. Appreciate if someone help me out on this.
I'd like to run some node code from my c#. Microsoft.AspNetCore.NodeServices seems to be the way to do this job however the examples are all very similar and all involve putting
services.AddNodeServices();
in the configure services function and then DI adds the implementation of INodeServices to a controller. Like this
public class foo
{
private readonly INodeServices _nodeServices;
public foo(INodeServices nodeServices)
{
_nodeServices = nodeServices;
}
}
As I'm using this in a class library rather than a webapi how is DI going to work? Also how do I call the class from a unit test, what can I pass into the constructor? I'm sure I'm missing something obvious.
The concept of DI is that it can be used to resolve object graphs. That is, it doesn't just resolve dependencies of the Controller class, but dependencies of those dependencies, dependencies of those dependencies, etc.
To use INodeServices in your own library, you simply need to reference Microsoft.AspNetCore.NodeServices, then accept it as a constructor parameter.
public class MyServiceFromMyLibrary : IMyServiceFromMyLibrary
{
private readonly INodeServices nodeServices;
public MyServiceFromMyLibrary(INodeServices nodeServices)
{
this.nodeServices = nodeServices;
}
// ...
}
Then reference your library from the Web API project and inject your service into a controller.
public class FooController
{
private readonly IMyServiceFromMyLibrary myService;
public FooController(IMyServiceFromMyLibrary myService)
{
this.myService = myService;
}
}
DI takes care of putting the INodeServices instance into your class provided it is registered in your composition root, as follows.
services.AddNodeServices();
services.AddTransient<IMyServiceFromMyLibrary, MyServiceFromMyLibrary>();
If your end game is to create a reusable library rather than an application layer refer to DI Friendly Library for some techniques to make your library easier to use without the use of dependency injection.
Also how do I call the class from a unit test, what can I pass into the constructor?
For a unit test, you would just need to mock INodeServices. The simplest way is to use a mocking library, such as Moq.
var mock = new Mock<INodeServices>();
mock.Setup(ns => ns.InvokeAsync(It.IsAny<string>())).Returns(...);
var target = new MyServiceFromMyLibrary(mock.Object);
// .. Call a method on target and then assert the results
References:
Using Node Services in ASP.NET Core
Dependency injection in ASP.NET Core
I am having a web api application written in c#, and i have used app insights to log the exceptions, so i have registered a service as follows,
private IExceptionLogService ExceptionLogService { get; set; }
and this is register inside the unity config as well,
<register type="IExceptionLogService" mapTo="ExceptionLogService" />
but when i run the application, the configuration shows in debug as well, it shows the file and the assembly.
private static IUnityContainer BuildUnityContainer()
{
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
var container = new UnityContainer().LoadConfiguration(section);
return container;
}
but when i try to resolve the dependencies it returns null
private void ResolveDependencies(HttpConfiguration configuration)
{
ExceptionLogService = ExceptionLogService ?? (IExceptionLogService)configuration.DependencyResolver.GetService(typeof(IExceptionLogService));
}
what is the issue here?
You register dependency in Unity DI container that implements IUnityContainer interface but trying to resolve dependency through HttpConfiguration.DependencyResolver of IDependencyResolver type. By default DependencyResolver is set to instance of System.Web.Http.Dependencies.EmptyResolver. It's clear from EmptyResolver class name that it's just a stub that performs no actual resolving.
You should either provide your own implementation of IDependencyResolver that wraps UnityContainer or use some existing implementation. Sample implementation is described in article Dependency Injection in ASP.NET Web API 2.
I suggest using of Unity.WebAPI NuGet package.
After you add this NuGet to your project, class UnityConfig will be added. Put your registrations to its RegisterComponents() method and add following call to Application_Start():
UnityConfig.RegisterComponents();
I've read the question Ioc/DI - Why do I have to reference all layers/assemblies in application's entry point?
So, in a Asp.Net MVC5 solution, the composition root is in the MVC5 project (and having a DependencyInjection assembly in charge of all the registrations does not make sense).
Within this picture, it is not clear to me what is the better approach among the following.
Approach 1
The concrete implementations are public class ... and all registrations clauses are centralized within the composition root (e.g. in one or more files under a CompositionRoot folder). MVC5 project must reference all the assemblies providing at least one concrete implementation to be bound. No library references the DI library. MVC project can contain interfaces to be bound with no drawbacks.
Approach 2
The concrete implementations are internal class .... Each library exposes a DI 'local' configuration handler. For example
public class DependencyInjectionConfig {
public static void Configure(Container container) {
//here registration of assembly-provided implementations
//...
}
}
which is up to register its own implementations. The composition root triggers registrations by calling all the Configure() methods, just one for each project. MVC5 project must then reference all the assemblies providing at least one concrete implementation to be bound. Libraries must reference the DI library. In this case, the MVC5 project cannot contain interfaces (otherwise there would be a circular reference): a ServiceLayer assembly would be needed to hold public interfaces to be bound.
Approach 3
Same as Approach 2, but local configuration modules are discovered dynamically through assembly reflection (by convention?). So MVC5 project has not to reference libraries. MVC project can contain interfaces and can be referenced by libraries. Libraries must reference the DI library.
What is the best practice here? Is there some other better possibility?
EDIT 1 (2016-12-22)
Thanks to received answers, I published this github project describing the best solution I found so far.
EDIT 2 (2018-09-09)
This answer provides an interesting option.
EDIT 3 (2020-12-29)
Finally, I came up with a complete solution, packaged in the form of a WebApi application template. I published this solution on GitHub HERE. This approach, not only gives a clear understanding about where DI rules have to be put, but also suggests to setup the application according to SOLID principles and CQRS pattern. The commit history of this project has been structured to have educational purposes.
EDIT 4 (2023-01-31)
The repository linked above publishes an article describing the solution as well.
I typically like to encapsulate these types of things into each project. So for example I might have the following. (This is an extremely simplified example, and I'll use the AutoFac in this example, but I'd imagine all DI frameworks have something like the following).
Common area for just POCOs and Interfaces.
// MyProject.Data.csproj
namespace MyProject.Data
{
public Interface IPersonRepository
{
Person Get();
}
public class Person
{
}
}
Implementation of Repositories and Data Access
// MyProject.Data.EF.csproj
// This project uses EF to implement that data
namespace MyProject.Data.EF
{
// internal, because I don't want anyone to actually create this class
internal class PersonRepository : IPersonRepository
{
Person Get()
{ // implementation }
}
public class Registration : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<PersonRepository>()
.As<IPersonRepository>()
.IntancePerLifetimeScope();
}
}
}
Consumer
// MyPrject.Web.UI.csproj
// This project requires an IPersonRepository
namespace MyProject.Web.UI
{
// Asp.Net MVC Example
internal class IoCConfig
{
public static void Start()
{
var builder = new ContainerBuilder();
var assemblies = BuildManager.GetReferencedAssemblies()
.Cast<Assembly>();
builder.RegisterAssemblyModules(assemblies);
}
}
}
So the Dependencies look like:
MyProject.Data.csproj
- None
MyProject.Data.EF.csproj
- MyProject.Data
MyProject.Web.UI.csproj
- MyProject.Data
- MyProject.Data.EF
In this setup, the Web.UI cannot know anything about what is registered nor for what reason. It only knows that the EF project has implementations but can't access them.
I can drop EF for say Dapper extremely easily as each project encapsulates it's own implementations and registration.
If I was adding unit tests and had an InMemoryPersonRepository, how would I swap out the PersonRepository for my InMemoryPersonRepository?
Assuming we ignore any business logic layer and have an MVC Controller directly access our Data Accessor, my code might look like:
public class MyController
{
private readonly IPersonRepository _repo;
public MyController(IPersonRepository repo)
{
_repo = repo;
}
public IActionResult Index()
{
var person = _repo.Get();
var model = Map<PersonVM>(person);
return View(model);
}
}
Then a test using nSubstitute Might look like:
public class MyControllerTests
{
public void Index_Executed_ReturnsObjectWithSameId
{
// Assign
var repo = Substitute.For<IPersonRepository>();
var expectedId = 1;
repo.Get().Returns(new Person { Id = expected });
var controller = new MyController(repo);
// Act
var result = controller.Index() as ActionResult<PersonVM>;
// Assert
Assert.That(expectedId, Is.EqualTo(result.Value.Id));
}
You've identified a real problem. (One could say it's a good problem to have.) If entry application Areferences B, B references C, and B and/or C require some DI registration, that makes A (your entry application) responsible for knowing enough about the details of B and C to register all the dependencies.
The solution is to have a separate assembly that handles composing all of the registrations for B and C. A references that, and it provides all of the container configuration that A needs to use B and C.
The benefits are
A doesn't know more about B and C than it should
Neither A, B, nor C have to be tied to one particular DI framework like Unity or Windsor.
Here's an example. This is an event bus class that works best with a DI container. But in order to use it you shouldn't have to know all about the dependencies it needs to register. So for Windsor I created a DomainEventFacility. You just call
_container.AddFacility<DomainEventFacility>();
and all of the dependencies are registered. The only thing you register are your event handlers.
Then if I want to use the same event bus library with a different DI container like Unity I can just create some similar assembly to handle the same configuration for Unity.