I have the following Controller interface:
public interface IInformationController
{
string GetStoredInformation();
string GetInformation();
}
The controller class is the following:
public class InformationController : ControllerBase, IInformationController
{
private InformationProvider1 InformationProvider1;
private InformationProvider2 InformationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository)
=> repository = basicRepository;
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";
}
I intend to create a unit test for the InformationController with xUnit and Moq.
This is my test class:
public class InformationControllerTest
{
public InformationControllerTest()
{
repositoryMock = new Mock<IBasicRepository>();
repositoryMock.Setup(repository => repository.GetStoredInformation()).Returns("Stored information");
SUT = new InformationController(repositoryMock.Object);
}
[Fact]
public void GetStoredInformation_Returns_Stored_Information()
{
string result = SUT.GetStoredInformation();
Assert.Equal("Stored information", result);
}
[Fact]
public void GetInformation_Returns_Valid_Information()
{
string result = SUT.GetInformation(); //TODO: how to avoid the usage of actual provider implementations?
Assert.Equal("Information is Header1, Information detail is Detail1", result);
}
}
As you can see, there are private providers. Unfortunately they are external dependencies and can't easily be introduced via dependency injection.
How should I mock their actual calls? Should I mock the controller method (which imho should invalidate the process of testing the actual controller)? Should I try to get them via dependency injection?
The unit test is exposing the short comings of your current design, which is tightly coupling to external dependencies or implementation concerns.
Dependencies should be explicitly injected into their dependents
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Reference Explicit Dependencies Principle
public class InformationController : ControllerBase, IInformationController {
private IInformationProvider1 informationProvider1;
private IInformationProvider2 informationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository,
IInformationProvider1 informationProvider1,
IInformationProvider2 informationProvider2) {
repository = basicRepository;
this.informationProvider1 = informationProvider1;
this.informationProvider2 = informationProvider2
}
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";
//...
}
Create abstractions and implementations for those external dependencies, then register them with the DI container so that they can be resolved and properly provided to the controller at run-time. This will now allow them to also be tested in isolation without undesired side effects from their actual implementations.
I have a class library where I want to access a Connectionstring from appsettings.json.
appsettings.json :
"DatabaseSettings": {
"ConnectionString": "Server=.;Database=Test;Trusted_Connection=True;"
},
In startup.cs I have the following code:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.AddOptions();
services.AddTransient<IConnectionOption, Class1>();
}
And in class library
IConnectionOption.cs
public interface IConnectionOption
{
void ReadValue();
}
Class1.cs
public class Class1 : IConnectionOption
{
private readonly DatabaseSettings test;
public Class1(IOptions<DatabaseSettings> dbOptions)
{
test = dbOptions.Value;
}
public void ReadValue()
{
var r = test;
}
}
Now from index.cshtml I want to Invoke the class Library Class1
public class IndexModel : PageModel
{
public void OnGet()
{
Class1 test = new Class1();
test.ReadValue();
}
}
But of course that doesnt work since there are no Constructor taking zero parameters, I don´t think I should add IOptions as an parameter. But how do I invoke the class library to read the connectionstring? (When I get this to work I will of course read data and return instead of the connectionstring). I have looked at several examples including net core 2.1 Dependency injection
But I don´t understand how to use the class library directly, Is it necessary to use an controller ?!
If DatabaseSettings is accessible to the class library, there really is not much need for tightly coupling Class1 library to IOptions, which is more framework related.
Ideally Class1 can explicitly depend on DatabaseSettings via explicit constructor injection
public class Class1 : IConnectionOption {
private readonly DatabaseSettings test;
public Class1(DatabaseSettings settings) {
test = settings;
}
public void ReadValue() {
var r = test;
//...
}
}
then in Startup, the dependency can be extract from configuration and registered with the DI container
public void ConfigureServices(IServiceCollection services) {
var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
services.AddSingleton<DatabaseSettings>(settings);
services.AddTransient<IConnectionOption, Class1>();
}
That way when ever Class1 is resolved, the container will know how to inject the DatabaseSettings dependency.
Another option could have also been to use the factory delegate
public void ConfigureServices(IServiceCollection services) {
var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
services.AddTransient<IConnectionOption, Class1>(_ => new Class1(settings));
}
That way, when the IndexModel depends on IConnectionOption for injection.
public class IndexModel : PageModel {
private readonly IConnectionOption connectionOption;
public IndexModel(IConnectionOption iConnectionOption) {
connectionOption = iConnectionOption;
}
public void OnGet() {
connectionOption.ReadValue();
//...
}
}
the proper dependency will be injected when the page model is initialized.
You are using Dependency Injection but only halfway. This is what you are missing:
Register the service in the container (I'm going to assume a better name for Class1):
services.AddScoped<IConnectionOption, DatabaseConnectionOption>();
Make the page receive the service:
public class IndexModel : PageModel
{
private readonly IConnectionOption _IConnectionOption;
public IndexModel(IConnectionOption iConnectionOption)
{
_IConnectionOption = iConnectionOption;
}
public void OnGet()
{
_IConnectionOption.ReadValue();
}
}
At this point I'm injecting things into my Controllers with ease, in some cases building my own ResolverServices class. Life is good.
What I cannot figure out how to do is get the framework to automatically inject into non-controller classes. What does work is having the framework automatically inject into my controller IOptions, which is effectively the configuration for my project:
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
public MessageCenterController(IOptions<MyOptions> options)
{
_options = options.Value;
}
}
I'm thinking whether I can do the same for for my own classes. I assume I'm close when I mimic the controller, like this:
public class MyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
}
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
I think where I'm failing is when I call it like this:
public void DoSomething()
{
var helper = new MyHelper(??????);
if (helper.CheckIt())
{
// Do Something
}
}
The problem I have tracking this down is practically everything that talks about DI is talking about it at the controller level. I tried hunting down where it happens in the Controller object source code, but it gets kinda crazy in there.
I do know I can manually create an instance of IOptions and pass it to the MyHelper constructor, but it seems like I should be able to get the framework do that since it works for Controllers.
Below is a working example of using DI without anything that involves MVC Controllers. This is what I needed to do to understand the process, so maybe it will help somebody else.
The ShoppingCart object gets, via DI, an instance of INotifier (which notifies the customer of their order.)
using Microsoft.Extensions.DependencyInjection;
using System;
namespace DiSample
{
// STEP 1: Define an interface.
/// <summary>
/// Defines how a user is notified.
/// </summary>
public interface INotifier
{
void Send(string from, string to, string subject, string body);
}
// STEP 2: Implement the interface
/// <summary>
/// Implementation of INotifier that notifies users by email.
/// </summary>
public class EmailNotifier : INotifier
{
public void Send(string from, string to, string subject, string body)
{
// TODO: Connect to something that will send an email.
}
}
// STEP 3: Create a class that requires an implementation of the interface.
public class ShoppingCart
{
INotifier _notifier;
public ShoppingCart(INotifier notifier)
{
_notifier = notifier;
}
public void PlaceOrder(string customerEmail, string orderInfo)
{
_notifier.Send("admin#store.com", customerEmail, $"Order Placed", $"Thank you for your order of {orderInfo}");
}
}
public class Program
{
// STEP 4: Create console app to setup DI
static void Main(string[] args)
{
// create service collection
var serviceCollection = new ServiceCollection();
// ConfigureServices(serviceCollection)
serviceCollection.AddTransient<INotifier, EmailNotifier>();
// create service provider
var serviceProvider = serviceCollection.BuildServiceProvider();
// This is where DI magic happens:
var myCart = ActivatorUtilities.CreateInstance<ShoppingCart>(serviceProvider);
myCart.PlaceOrder("customer#home.com", "2 Widgets");
System.Console.Write("Press any key to end.");
System.Console.ReadLine();
}
}
}
Let's say MyHelper is used by MyService which in turn is used by your controller.
The way to resolve this situation is:
Register both MyService and MyHelper in Startup.ConfigureServices.
services.AddTransient<MyService>();
services.AddTransient<MyHelper>();
The controller receives an instance of MyService in its constructor.
public HomeController(MyService service) { ... }
MyService constructor will in turn receive an instance of MyHelper.
public MyService(MyHelper helper) { ... }
The DI framework will be able resolve the whole object graph without problems. If you are worried about new instances being created every time an object is resolved, you can read about the different lifetime and registration options like the singleton or request lifetimes.
You should be really suspicious when you think you have to manually create an instance of some service, as you might end up in the service locator anti-pattern. Better leave creating the objects to the DI Container. If you really find yourself in that situation (let's say you create an abstract factory), then you could use the IServiceProvider directly (Either request an IServiceProvider in your constructor or use the one exposed in the httpContext).
var foo = serviceProvider.GetRequiredService<MyHelper>();
I would recommend reading the specific documentation about the ASP.Net 5 DI framework and about dependency injection in general.
Unfortunately there is no direct way. The only way I managed to make it work is by creating a static class and using that everywhere else as below:
public static class SiteUtils
{
public static string AppName { get; set; }
public static string strConnection { get; set; }
}
Then in your startup class, fill it in as below:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//normal as detauls , removed for space
// set my variables all over the site
SiteUtils.strConnection = Configuration.GetConnectionString("DefaultConnection");
SiteUtils.AppName = Configuration.GetValue<string>("AppName");
}
Although this is bad pattern, as this will stay for the whole life cycle of the application and I couldn't find better way to use it outside controller.
Here's a more complete example to directly answer the OP's question, based on the current .NET Core 2.2 DI documentation here. Adding this answer since it may help someone that's new to .NET Core DI, and because this question is Google's top search result.
First, add an interface for MyHelper:
public interface IMyHelper
{
bool CheckIt();
}
Second, update the MyHelper class to implement the interface (in Visual Studio, press ctrl-. to implement the interface):
public class MyHelper : IMyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
{
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
Third, register the interface as a framework-provided service in the DI service container. Do this by registering the IMyHelper service with the concrete type MyHelper in the ConfigureServices method in Startup.cs.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IMyHelper, MyHelper>();
...
}
Fourth, create a private variable to reference an instance of the service. Pass the service as an argument in the constructor (via constructor injection) then initialize the variable with the service instance. Reference any properties or call methods on this instance of the custom class via the private variable.
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
private readonly IMyHelper _myHelper;
public MessageCenterController(
IOptions<MyOptions> options,
IMyHelper myHelper
)
{
_options = options.value;
_myHelper = myHelper;
}
public void DoSomething()
{
if (_myHelper.CheckIt())
{
// Do Something
}
}
}
You may use Activator.CreateInstance(). Here is a wrapper function for it. The way you use this is as follows.
var determinedProgrammatically = "My.NameSpace.DemoClass1"; // implements IDemo interface
var obj = CreateInstance<My.NameSpace.IDemo, string>(determinedProgrammatically, "This goes into the parameter of the constructor.", "Omit this parameter if your class lives in the current assembly");
Now you have an instance of obj which is instantiated from type determined programmatically. This obj can be injected into non controller classes.
public TInterface CreateInstance<TInterface, TParameter>(string typeName, TParameter constructorParam, string dllName = null)
{
var type = dllName == null ? System.Type.GetType(typeName) :
System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith(dllName, System.StringComparison.OrdinalIgnoreCase)).GetType(typeName);
return (TInterface)System.Activator.CreateInstance(type, constructorParam);
}
PS: You may iterate through System.AppDomain.CurrentDomain.GetAssemblies() to determine the name of the assembly that houses your class. This name is used in the 3rd parameter of the wrapper function.
TL;DR: You can save a singleton in a static var and then access it form other classes, but this an anti-pattern, use with caution.
Long version:
As per this question Resolving instances with ASP.NET Core DI from within ConfigureServices
Any services registered in ConfigureServices() can then be injected
into the Configure() method
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<FooService>();
}
public void Configure(IApplicationBuilder app, FooService fooService)
{
FooServiceInstance = fooService;
}
public static FooService FooServiceInstance { get; private set; }
And then call it from your other code MyStartupClass.FooService.DoStuff()
I'm trying to create an instance of an object from a web.config configuration, like this:
<add name="Log4Net" type="Spm.Services.Logging.Log4NetServices.Log4NetReporting, Spm.Services" />
The type Log4NetReporting has a constructor with an argument I want to inject, like this:
public class NLogReporting : ILogReporting
{
[Inject]
public NLogReporting(IRepository<NLogError> nLogRepository)
{
this.nLogRepository = nLogRepository;
}
}
I was trying to create an instance of this object by doing this:
var logger = Activator.CreateInstance(type) as ILogReporting;
But I get an exception saying "No parameterless constructor has been define for this object".
Ideally, I would like to do this using Ninject but I don't know how. My code is separated in different assemblies so the Ninject initialization (look below) is in one assembly (the Web application assembly) and this code is in the Services assembly.
Here's my Ninject initialization code:
private static StandardKernel CreateNinjectKernel()
{
var kernel = new StandardKernel();
RegisterNinjectServices(kernel);
ConfigureAutoMapper(kernel);
return kernel;
}
private static void RegisterNinjectServices(IKernel kernel)
{
kernel.Bind<IRepository<NLogError>>().To<Repository<EntityDbContext, NLogError>>().InRequestScope();
}
Is this possible to do or am I just doing it all wrong?
/Ingo
ideally you would have ILogReporting injected into the service that would use it.
public class SomeService : ISomeService
{
private readonly ILogReporting _logger;
public SomeService(ILogReporting logger)
{
_logger = logger;
}
// .... code....
}
but if you need to request the instance at the time of execution, not creation, then you will need some way to access the DI container (the Ninject Kernel) from wherever you are trying to get the ILogReporting instance. Ninject's WebAPI integration wires its Kernel up to the System.Web.Mvc.IDependencyResolver, so we can use that.
public class SomeService : ISomeService
{
private readonly IDependencyResolver _resolver;
public SomeService(IDependencyResolver resolver)
{
_resolver = resolver;
}
public void Execute()
{
var logger = _resolver.GetService<ILogReporting>();
// .... code....
}
}
How do you debug dependency injection (using Unity DI) when the dependancy does not instantiate?
eg Given a service class with dependencies:
public class FooService : IFooService
{
[Dependency]
public BarService BarService { get; set; }
[Dependency]
public AnotherService AnotherService { get; set; }
// other code fails because BarService and AnotherService are null
}
And in Global.asax.cs
private void ConfigureIoC()
{
container
.ConfigureAutoRegistration()
.LoadAssembliesFrom(assemblyPaths)
.ExcludeSystemAssemblies()
.Include(If.Any, Then.Register())
.ApplyAutoRegistration();
var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
}
The IFooService is also instantiated by Unity, but that uses constructor injection instead (and it works):
public class FooController : Controller
{
private readonly IFooService _fooService;
public FooController(IFooService fooService)
{
_fooService = fooService;
}
}
How can I debug this to see why the dependencies are failing to instantiate. No exceptions are being thrown (or if they are then Elmah is not catching and logging them).
The dependency is not injected because the DependencyAttribute is on the concrete class instead of the interface.
As DI attributes can be harmful I would recommend you change the registration to
container.RegisterType<IFooService,FooService>(new InjectionProperty("BarService"), new InjectionProperty("AnotherService"));
Resolving IFooService will then return an instance of FooService with the injected dependencies.
Call container.Resolve<IFooService>();
Where/how is resolution of IFooService happening?