I am struggling to determine if this is the correct method for injecting dependencies from my Console Application Main method into my primary application class instance.
I have the following code:
Program Class
static void Main(string[] args)
{
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
//Verify the container.
container.Verify();
ILogger log = container.GetInstance<ILogger>();
log.Info("Logging From Main Method");
//Start Main Agent
MainAgent agent = new MainAgent(log);
agent.Start();
}
Main Agent Class
public class MainAgent
{
private ILogger log;
public MainAgent(ILogger _log)
{
log = _log;
}
public void Start()
{
//Main Application Code here.
Console.WriteLine("main Agent Started.");
log.Info("Logging through logger in MainAgent Class");
Console.ReadLine();
}
}
I come from a background of writing DotNetCore applications in ASP.Net Core, so I am used to how the DI works with that, registering a service into the pipeline, and them all being available for me to cherry pick in each controller's Constructor.
My worry is I may have 20-30 services, all of which will all need to be injected in as parameters each time I “New Up” a new instance of a class for them to be avaliable to the constructor in my new class.
Am I missing some magical feature which will just make all my registered services available in any newly initialized constructor for me to reference as I do with ASP.Net Core?
No, there is no magic.
What you are missing is that AspNetCore automatically resolves your controller under the covers, which resolves the entire object graph of dependencies that controller has (that is, any dependencies of the controller, dependencies of those dependencies, etc.)
Similarly, in a console app, you need to resolve the entire object graph (usually at startup).
static void Main(string[] args)
{
// Begin Composition Root
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
container.Register<IMainAgent, MainAgent>();
//Verify the container.
container.Verify();
// End Composition Root
MainAgent agent = container.GetInstance<IMainAgent>();
//Start Main Agent
agent.Start();
}
Effectively the "agent" is should be considered to be the entire application. The console is just a shell to set everything in motion. Do note that it would probably be sensible in most situations to pass in the args from the console app, so they can be parsed and responded to by the "agent" as appropriate.
agent.Start(args);
Am I missing some magical feature which will just make all my registered services available in any
Simple answer yes you are SimpleInjector supports direct object creation
var agent = container.GetInstance<MainAgent>();
With out the need to register the instance at all.
You can make an interface and then register like you do ILogger but making the method virtual and using directly the class name is also fine. You can read more on the subject here
Related
I am looking for guidance on how to correctly and safely dispose of registered singleton instances when my ASP.NET Core 2.0 app is shutting down.
According to the following document, if I register a singleton instance (via IServiceCollection) the container will never attempt to create an instance (nor will it dispose of the instance), thus I am left to dispose of these instances myself when the app shuts down.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.0 (2.1 has the same guidance)
I enclose some pseudo code that illustrates what I am trying to achieve.
Note I am having to maintain a reference to IServiceCollection since the IServiceProvider provided to the OnShutDown method is a simple service locator and doesn't give me the ability to execute complex queries.
When the app shuts down I want a generic way to ensure all singleton instances are disposed. I could maintain a reference to all these singleton instances directly but this doesn't scale well.
I originally used the factory method which would ensure the DI managed the lifetime of my objects, however, the execution of the factory method happened at runtime in the pipeline of handling a request, which meant that if it threw an exception the response was 500 InternalServerError and an error was logged. By creating the object directly I am striving for faster feedback so that errors on startup lead to a automatic rollback during the deployment. This doesn't seem unreasonable to me, but then at the same time I don't to misuse the DI.
Does anyone have any suggestions how I can achieve this more elegantly?
namespace MyApp
{
public class Program
{
private static readonly CancellationTokenSource cts = new CancellationTokenSource();
protected Program()
{
}
public static int Main(string[] args)
{
Console.CancelKeyPress += OnExit;
return RunHost(configuration).GetAwaiter().GetResult();
}
protected static void OnExit(object sender, ConsoleCancelEventArgs args)
{
cts.Cancel();
}
static async Task<int> RunHost()
{
await new WebHostBuilder()
.UseStartup<Startup>()
.Build()
.RunAsync(cts.Token);
}
}
public class Startup
{
public Startup()
{
}
public void ConfigureServices(IServiceCollection services)
{
// This has been massively simplified, the actual objects I construct on the commercial app I work on are
// lot more complicated to construct and span several lines of code.
services.AddSingleton<IDisposableSingletonInstance>(new DisposableSingletonInstance());
// See the OnShutdown method below
this.serviceCollection = services;
}
public void Configure(IApplicationBuilder app)
{
var applicationLifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();
applicationLifetime.ApplicationStopping.Register(this.OnShutdown, app.ApplicationServices);
app.UseAuthentication();
app.UseMvc();
}
private void OnShutdown(object state)
{
var serviceProvider = (IServiceProvider)state;
var disposables = this.serviceCollection
.Where(s => s.Lifetime == ServiceLifetime.Singleton &&
s.ImplementationInstance != null &&
s.ServiceType.GetInterfaces().Contains(typeof(IDisposable)))
.Select(s => s.ImplementationInstance as IDisposable).ToList();
foreach (var disposable in disposables)
{
disposable?.Dispose();
}
}
}
}
It's the DI's job to dispose of any IDisposable objects it creates, whether transient, scoped or singleton. Don't register existing singletons unless you intend to clean them up afterwards.
In the question's code there's no reason to register an instance of DisposableSingletonInstance. It should be registered with :
services.AddSingleton<IDisposableSingletonInstance,DisposableSingletonInstance>();
When the IServiceCollection gets disposed, it will call Dispose() on all the disposable entities created by it. For web applications, that happens when RunAsync() ends;
The same holds for scoped services. In this case though, the instances will be disposed when the scope exits, eg when a request ends.
ASP.NET creates a scope for each request. If you want your service to be disposed when that request ends, you should register it with :
services.AddScoped<IDisposableSingletonInstance,DisposableSingletonInstance>();
Validation
For the latest edit :
By creating the object directly I am striving for faster feedback so that errors on startup lead to a automatic rollback during the deployment.
That's a different problem. Deployment errors are often caused by bad configuration values, unresponsive databases etc.
Validating Services
A very quick & dirty way to check would be to instantiate the singleton once all startup steps are complete with :
services.GetRequiredService<IDisposableSingletonInstance>();
Validating Configuration
Validating the configuration is more involved but not that tricky. One could use Data Annotation attributes on the configuration classes for simple rules and use the Validator class to validate them.
Another option is to create an IValidateable interface with a Validate method that has to be implemented by each configuration class. This makes discovery easy using reflection.
This article shows how the IValidator interface can be used in conjunction with an IStartupFilter to validate all configuration objects when an application starts for the first time
From the article :
public class SettingValidationStartupFilter : IStartupFilter
{
readonly IEnumerable<IValidatable> _validatableObjects;
public SettingValidationStartupFilter(IEnumerable<IValidatable> validatableObjects)
{
_validatableObjects = validatableObjects;
}
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
foreach (var validatableObject in _validatableObjects)
{
validatableObject.Validate();
}
//don't alter the configuration
return next;
}
}
The constructor gets all instances that implement IValidatable from the DI provider and calls Validate() on them
That's not accurate. Singletons are disposed at app shutdown, though it's kind of not actually all that relevant because when the process stops, everything goes with it anyways.
The general rule of thumb is that when using DI, you should use DI all the way down, which then means you'll almost never be disposing on your own, anywhere. It's all about ownership. When you new stuff up yourself, you're also then responsible for disposing of it. However, when using DI, the container is what's newing things up, and therefore, the container and only the container should then dispose of those things.
Thanks for the responses Panagiotis Kanavos and Chris Pratt and for helping to clarify how best to deal with this scenario. The two take away points are this:
Always strive to let the container manage the life cycle of your objects so when the app is shutdown the container will automatically dispose of all objects.
Validate all your configuration on app startup before it is consumed by objects registered in the container. This allows your app to fail fast and protects your DI from throwing exceptions when creating new objects.
I'm registering a service as a singleton in .NET Core. Yet I'm seeing the constructor for the singleton called multiple times.
services.AddSingleton<DbAuthorizationOptions, ContextAuthorizationOptions>();
My context authorization options is just Dictionary of Entity Types to IValidators, The context authorization options are passed into the DBContext, to automatically run validations.
During the registration of my services, I also register dynamic Validators with my container registered in DI.
var useDynamicValidator = serviceOption.ValidatorOptions != null;
if(useDynamicValidator)
{
//TODO: Extract this to before the register service no sense in building the provider each time
//TODO: Make this cleaner don't be dependent on Authorization options
var provider = services.BuildServiceProvider();
var authOptions = provider.GetService<DbAuthorizationOptions>();
var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
authOptions.ValidatorOptions.AddValidatorForSet(validator);
}
I notice that when I call GetService on the provider I receive a new singleton instead of the existing one. Does building the provider create a new container so all of the services get re-registered?
If so, How can I call a method to register my dynamic validators in the singleton container with the existing IServiceProvider, is there a way to invoke some registration once after the service container is built?
Does building the provider create a new container so all of the services get reregistered?
Yes. See the source code.
If so, How can I call a method to register my dynamic validators in the singleton container with the existing IServiceProvider, is there a way to invoke some registration once after the servicecontainer is built?
I'm not really understanding why this is a problem. You should be registering all of your services one time at application startup in the Composition Root.
The DI container is then responsible for resolving the object graphs of the application. The application itself shouldn't have a dependency on it, nor be required to update it.
You should be injecting DbAuthorizationOptions in the place where you need to use it.
public class Foo : IFoo
{
private readonly DbAuthorizationOptions authOptions;
public Foo(DbAuthorizationOptions authOptions) // <-- Inject parameters
{
this.authOptions = authOptions ??
throw new ArgumentNullException(nameof(authOptions));
}
public void DoSomething()
{
// TODO: Inject the type that has the BuildDynamicValidatorFactory
// method and the serviceOption (whatever type that is) here
// either as a method parameter of this method, or a constructor
// parameter of this class.
var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
// Now we have an instance of authOptions that can be used
authOptions.ValidatorOptions.AddValidatorForSet(validator);
}
}
Note that the DI container automatically provides the DbAuthorizationOptions if injected into another type that is also resolved through DI (such as a controller or filter).
NOTE: It isn't very clear from your question where you need to do this. You mention that you want it to happen once, which usually means to put it at application startup. But users cannot interact with code that runs at startup. So, maybe you could use a filter. It really all depends on where in the lifecycle of the application it has to happen.
You can declare a dependency on IServiceProvider -- don't build it, inject it.
public class SomeController
{
DbAuthorizationOptions authOptions;
public SomeController(IServiceProvider provider)
{
authOptions = provider.GetSerivce<DbAuthorizationOptions>();
}
}
But this is the service locator anti-pattern. As I commented on NightOwl888's post after you gave more details, a factory is probably a better approach.
I have the following resolver in my WebApi project:
config.DependencyResolver = new UnityResolver(container); // HttpConfiguration config
However in a console app, I don't have HttpContiguration. How can I tell my unity container to use this DependencyResolver from my console app?
There might be a better way, but I do my registrations, and then let the container resolve my "first" class.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Registering dependencies ...");
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>(); // Register a class that continues your program.
// Do your registrations.
RegisterTypes(container);
// Let Unity resolve ProgramStarter and create a build plan.
var program = container.Resolve<ProgramStarter>();
Console.WriteLine("All done. Starting program...");
program.Run();
}
}
And my ProgramStarter class.
public class ProgramStarter
{
private readonly IService _service;
public ProgramStarter(IService service)
{
// Unity has created this instance and resolved all dependencies.
_service= service;
}
public void Run()
{
// Do what you want to do.
}
}
You don't. The UnityResolver exists to interact with the MVC framework. A console application is no framework and there are no framework types that a Console Application tries to create for you. Since there is no framework, no special hooks are required to use a DI container in a console application. You simply create the container and have one container.Resolve call to construct the object graph and call the method on the resolved object.
I'm trying to figure out how to resolve a instance somewhere in the code.
At the application startup I registered a type
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Foo>().As<IFoo>();
}
Now, how can I resolve an instance somewhere in the code ?
In StructureMAP there is a static object ObjectFactory.GetInstance<IFoo>()
Read up on Getting Started. It should get you started.
First off, what you are looking for is the container. Build it from the ContainerBuilder like in this simple WinForms app:
static void Main()
{
using (var container = builder.Build())
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = container.Resolve<MainForm>();
Application.Run(mainForm)
}
}
The general idea is that you only have to resolve the first or topmost instance. The container will handle creating all other instances based on dependency injection through constructor parameters.
If the DI pattern is followed throughout your application you should only have to touch the container once at startup.
How you resolve the topmost instance depends largely on what type of application you are building. If its a web app, the ASP.Net integration and MVC integration will take care of it for you. (After all, the topmost instance in ASP.Net is the Application which is out of our control).
On the other hand, if its a console app or WinForms app you would resolve the first instance manually in Main, like my sample above.
I just started using the Unity Application Block to decouple my classes and make unit testing easier. However, I've run into a problem with circular dependencies.
I have a facade-type class which is a chat bot. It is a singleton class which handles all sort of secondary classes and provides a central place to launch and configure the bot. I also have a class called AccessManager which, well, manages access to bot commands and resources. Boiled down to the essence, I have the classes set up like so:
public class Bot
{
public string Owner { get; private set; }
public string WorkingDirectory { get; private set; }
private IAccessManager AccessManager;
private Bot()
{
// do some setup
// LoadConfig sets the Owner & WorkingDirectory variables
LoadConfig();
// init the access mmanager
AccessManager = new MyAccessManager(this);
}
public static Bot Instance()
{
// singleton code
}
...
}
And the AccessManager class:
public class MyAccessManager : IAccessManager
{
private Bot botReference;
public MyAccesManager(Bot botReference)
{
this.botReference = botReference;
SetOwnerAccess(botReference.Owner);
}
private void LoadConfig()
{
string configPath = Path.Combine(
botReference.WorkingDirectory,
"access.config");
// do stuff to read from config file
}
...
}
I would like to change this design to use the Unity Application Block. I'd like to use Unity to generate the Bot singleton and to load the AccessManager interface in some sort of bootstrapping method that runs before anything else does.
public static void BootStrapSystem()
{
IUnityContainer container = new UnityContainer();
// create new bot instance
Bot newBot = Bot.Instance();
// register bot instance
container.RegisterInstance<Bot>(newBot);
// register access manager
container.RegisterType<IAccessManager,MyAccessManager>(newBot);
}
And when I want to get a reference to the Access Manager inside the Bot constructor I can just do:
IAcessManager accessManager = container.Resolve<IAccessManager>();
And elsewhere in the system to get a reference to the Bot singleton:
// do this
Bot botInstance = container.Resolve<Bot>();
// instead of this
Bot botInstance = Bot.Instance();
The problem is the method BootStrapSystem() is going to blow up. When I create a bot instance it's going to try to resolve IAccessManager but won't be able to because I haven't registered the types yet (that's the next line). But I can't move the registration in front of the Bot creation because as part of the registration I need to pass the Bot as a parameter! Circular dependencies!! Gah!!!
This indicates to me I have a flaw in the way I have this structured. But how do I fix it? Help!!
You can make your life easier by changing the design in the following ways:
Don't implement the Singleton pattern yourself. The DI Container should manage the lifetime of all components, including the Bot class. If you only want a single instance in your application, configure Unity to always return the same instance.
Do everything in your power to remove circular dependencies. You can often do that by changing one of the communication directions to use events instead of direct calls. Another option is to introduce a Mediator.
Notice that none of these recommendations particularly involve Unity. Unity (or any other DI Container) is not a silver bullet that will magically make your code loosely coupled. You must first understand the principles behind DI, and then you can use any DI Container as a tool to help you wire up the dependency graph.
First of all you should let the container manage your singleton lifetime instead of writing the singleton code yourself. To remove your circular dependency, you can remove the Bot from the access manager constructor. Instead, you use an initialize method.
container.RegisterType<Bot>(new ContainerControlledLifecycleManager()); // from my memory...
container.RegisterType<IAccessManager,MyAccessManager>();
var bot = container.Resolve<Bot>();
// Bot.cs
public Bot(IAccessManager manager)
{
manager.InitializeFor(this);
}
For testability reasons you should never call your IOC container from a constructor.