I've been looking through the Simple Injector documentation and thought I was doing things right regarding Crosswiring, but alas...
I have the following which fails to resolve my App through the IServiceProvider
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SimpleInjector;
using SimpleInjector.Lifestyles;
using SimpleInjectorTesting;
Container container = new Container { Options = { DefaultScopedLifestyle =
new AsyncScopedLifestyle()}};
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Information))
.ConfigureServices((hostBuilderContext, services) =>
{
container.RegisterSingleton<App>();
services.AddSingleton<ISaySomethingService, SaySomethingService>();
services.AddSimpleInjector(container);
})
.Build();
host.Services.UseSimpleInjector(container);
container.Verify();
var app = host.Services.GetRequiredService<App>();
//var app = container.GetInstance<App>();
await app.Run();
If I switch to use the container.GetInstance<App>() call the it works fine, SI can resolve services registered from IServiceCollection.
If I set options.AddLogging() to SI, an IServiceProvider registered type can't receive ILogger even if I'm using container.GetInstance<App>()
System.InvalidOperationException: 'The configuration is invalid. Creating the instance for type App failed. The registered delegate for type ISaySomethingService threw an exception. Failed to resolve ISaySomethingService. ISaySomethingService is a cross-wired service, meaning that Simple Injector forwarded the request the framework's IServiceProvider in order to get an instance. The used Microsoft.Extensions.DependencyInjection.ServiceProvider, however, failed with the following message: "Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'SimpleInjectorTesting.SaySomethingService'.". This error might indicate a misconfiguration of services in the framework's IServiceCollection.'
So I have this library that does a bunch of stuff using SI and leverages decorators, conditionals, etc that standard .NET DI makes difficult but I want this library to be usable by anyone who may not be using Simple Injector. I have an extension method to Register my framework and then another to use it which does the container.Verify() call to get the SI specific stuff tucked away. But then I can't resolve through IServiceProvider as per the code above. Is this even possible with SI and if so what am I missing?
Update:
This is my App class
public class App
{
private readonly ISaySomethingService _saySomethingService;
public App(ISaySomethingService saySomethingService)
{
_saySomethingService = saySomethingService;
}
public async Task Run(CancellationToken cancellationToken = default)
{
Console.WriteLine(_saySomethingService.Message());
}
}
When it comes to integration with an .NET Core or ASP.NET Core application, Simple Injector works very differently compared to for instance Autofac. This has to do with the design choices made by Microsoft and their incompatibility with Simple Injector's design. I discussed this in detail here and here.
But this is why choosing Autofac for your DI container in an ASP.NET Core application, Autofac ends up replacing the entire DI infrastructure, which means all application, framework, and third-party registrations will be made in Autofac.
When choosing Simple Injector, on the other hand, the Simple Injector container will run side-by-side with the original MS.DI container. This means that you, as an application develop, will register your application components as part of Simple Injector, while framework and third-party libraries that depend on the IServiceCollection abstraction, will effectively use MS.DI as their backing container.
The Simple Injector integration package for .NET Core, however, does allow a feature called "cross wiring" or "auto cross wiring", which allows the Simple Injector container to resolve services from the built-in MS.DI container to inject them into your Simple Injector-resolved application components. This feature is implemented using Simple Injector's unresolved type resolution. As there is no such feature in MS.DI, it's not possible to let MS.DI automatically callback into Simple Injector to fetch missing dependencies. You can always do this on a per-service basis by making an explicit registration to MS.DI though, e.g. services.AddTransient<IService>(_ => container.GetInstance<IService>()).
In the majority of cases, however, you shouldn't need to be able to 'cross wire' back from MS.DI to Simple Injector, because the dependency would typically go from application component towards framework (or third-party) abstraction; not the other way around.
But the fact that Simple Injector doesn't replace the built-in DI infrastructure (but run side-by-side) does have the consequence that adding registrations to the IServiceCollection doesn't add them to Simple Injector. And this means that if you have a third-party library (or self-built NuGet package) that integrated with IServiceColllection, this won't run as part of Simple Injector.
Under normal conditions this wouldn't be a problem, because its okay for framework and third-party components to be composed by MS.DI, especially because Simple Injector makes it easy to pull them in. You, as an application developer, would typically don't see the difference (although it's important to understand what to register where).
But your case is different, because you are building a reusable library with application-specific abstractions (and implementations) while you want to simplify registration for the application developers using these abstractions. Adding a AddMyReusableLibrary(this IServiceCollection) method to that library will work when the end application is completely relying on MS.DI or Autofac, but won't help when the application uses Simple Injector.
There are a few options here:
You build an extra NuGet package, say MyReusableLibrary.SimpleInjector that depends on both MyReusableLibrary and SimpleInjector, and adds an AddMyReusableLibrary(this SimpleInjector.Container) method, or
You simply document what registrations need to be made to Simple Injector. It will typically be a handful of registrations. This gives the application developer full control and knowledge about the made registrations, although, admittingly, does cause some more code in the application's Composition Root, and doesn't allow new features in vNext of your MyReusableLibrary to get automatically added.
You design your reusable library according to Mark Seemann's advice on DI-friendly libraries. Although, in your case that unlikely helps because your reusable library actually contains application abstractions. It is a reusable library as in -it is a NuGet package-, but in fact contains parts of the application's core design and domain.
Related
Could someone expand upon the directions Halil Kalkan (#hikalkan) provided here: https://github.com/volosoft/castle-windsor-ms-adapter
ORIGINAL - works using standard Microsoft DI
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper();
services.AddMvc();
services.AddApiVersioning();
services.AddDbContextPool<CIDMSContext>(options => options.UseSqlServer(""));
services.AddScoped<IBuildingRepository, BuildingRepository>();
services.AddScoped<IComponentRepository, ComponentRepository>();
}
NEW - does not work. trying to use Castle.Windsor.MsDependencyInjection
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper();
services.AddMvc();
services.AddApiVersioning();
services.AddDbContextPool<CIDMSContext>(options => options.UseSqlServer(""));
//services.AddScoped<IBuildingRepository, BuildingRepository>();
//services.AddScoped<IComponentRepository, ComponentRepository>();
return WindsorRegistrationHelper.CreateServiceProvider(
new WindsorContainer(), services);
}
I am getting the error:
Unable to resolve service for type '...Repositories.Buildings.IBuildingRepository' while attempting to activate ...Controllers.BuildingController'
My ultimate goal is to not have to DI every single repository that I ever create. I would like Castle Windsor to DI it by convention. If there are other options to doing this for .Net Core 2.0 then I am open to those options as well.
I am using Visual Studio 15.4.1 .Net Core 2.0 API project.
EDIT:
CastleWindsor - ASP.NET Core Facility
I would advise against using such adapter. Creating a good (fully compatible) adapter on top of the new .NET Core DI abstraction has proven to be a far from trivial task for most DI Containers. Some Containers are simply not compatible with the way Microsoft built their DI Container and Castle Windsor is a good example.
The Castle Windsor maintainers have tried for quite some time to build such an adapter, but even after consulting Microsoft about this, Microsoft acknowledged (copy) Castle Windsor is incompatible to how MS views the world of containers.
Castle isn't the only container that falls into this category. Contains such as Simple Injector, Ninject, Unity and StructureMap have proven to be incompatible with the new .NET Core DI Abstraction as well. Although StructureMap actually has an adapter, their adapter isn't 100% compatible with the abstraction, which might obviously lead to problems when the ASP.NET Core framework, or a third-party library, starts to depend on that incompatible behavior. And even for other containers with an adapter, like Autofac and LightInject, problems with their adapters seem to keep popping up, which proves (IMO) the the underlying model is flawed.
So at this moment in time there is no compatible adapter for Castle Windsor, and the Castle Windsor maintainers haven't decided yet whether they should or even could adapt.
But the absense of a compatible adapter is not a problem at all. Windsor (and other containers) can quite easily be integrated with ASP.NET Core without the use of an adapter, as fir3pho3nixx stated on the Windsor forum here. In its basics, it’s just a few lines of code to get things running.
UPDATE:
Windsor has now a Facility (integration package) for ASP.NET Core, the documentation for which can be read here. Note that the Windsor maintainers chose not to create an adapter implementation. The Facility works by keeping the built-in DI system in place instead of replacing it. From a consumer's point of view, however, how the Facility works is not that interesting.
I have the following code snippet in my application:
services.AddScoped<IMyInterface, MyService>();
services.AddSingleton<IYourInterface, YourService>();
Due to some environment initialization process, I have to be able to obtain the singleton instance of IYourInterface within Startup class to call the service to read a couple of configuration entries from a remote server and populate them. How can I achieve this goal considering the fact that I am using .Net Core's built-in DI framework?
The way to do this to create this instance manually up front as follows:
var service = new YourService();
services.AddScoped<IMyInterface, MyService>();
services.AddSingleton<YourService>(service);
Just as it is wise to separate the registration process from use (as the Microsoft.Extensions.DependencyInjection library correctly forces), this kind of separation is important between loading/building configuration and making the container registrations. Doing register-resolve-register is unsupported by libraries like MS DI, Autofac and Simple Injector, because it can lead to lots of complexity and subtle bugs.
I am currently using Simple Injector to resolve dependencies into my Asp.Net Web Api projects.
From the documentation you can configure it like that:
protected void Application_Start() {
// Create the container as usual.
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
// Register your types, for instance using the scoped lifestyle:
container.Register<IUserRepository, SqlUserRepository>(Lifestyle.Scoped);
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
// Here your usual Web API configuration stuff.
}
The main points here are to register the Web Api controllers and set a custom dependency resolver.
However I've just read these article from Mark Seemann on how to configure dependency injection in Asp.Net Web Api:
Dependency Injection and Lifetime Management with ASP.NET Web API
Dependency Injection in ASP.NET Web API with Castle Windsor
From these articles, I've learnt that there is a better option than implementing IDependencyResolver to resolve Web Api dependencies.
This other option is to create an implementation of the IHttpControllerActivator that acts as an Adapter over the IoC Container.
Here is the implementation I've coded using SimpleInjector:
public class SimpleInjectorControllerActivator : IHttpControllerActivator
{
private readonly Container _container;
public SimpleInjectorControllerActivator(Container container)
{
_container = container;
}
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
request.RegisterForDispose(_container.BeginExecutionContextScope());
return (IHttpController)_container.GetInstance(controllerType);
}
}
and in the Application_Start method, I've replaced this line:
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
by this line :
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new SimpleInjectorControllerActivator(container));
I would like to know if the implementation of the IHttpControllerActivator is valid and also if this approach is valid and will work as good as the normal one ?
Yes, your implementation is valid.
Only be careful not to use both the SimpleInjectorWebApiDependencyResolver and the SimpleInjectorControllerActivator in the same application. Both start an ExecutionContextScope which could lead to having two scopes within the same web request, so they are mutually exclusive.
A general advantage of using a controller activator over the dependency resolver is that the dependency resolver contract forces the adapter to return null when a service can't be created. This is a very common problem that developers run into, and it often causes the confusing controller does not have a default constructor exception. This problem does not exist when using an IHttpControllerActivator, since the contract forces you to return a value or throw an exception.
The Simple Injector Web API integration project however, prevents this problem with dependency resolver, by never returning null (but throwing an exception instead) in case the requested service is an API controller (and thereby implicitly breaking the IDependencyResolver's contract).
An advantage of using the SimpleInjectorDependencyResolver is that it becomes easier to create message handlers that operate within the execution context scope, since you can trigger the creation of this scope by calling request.GetDependencyScope() method. With the current implementation, the scope just gets started at the time that the controller gets created, which is after you run the handlers. Changing this isn't that hard, but involves changing your controller activator and have an outermost handler that starts the execution context scope (or again falling back on a dependency resolver that manages the execution context scope).
One of the arguments of Mark Seemann is that it becomes hard to pass context around, which is a very valid point, as long as your components don't require this context during construction. But this is not a problem you'll experience when using Simple Injector, because there is an extension method that helps you with accessing the HttpRequestMessage. So although the IDependencyResolver abstraction isn't designed for getting the contextual information, there are ways to get this contextual information.
In the past we decided to go with an adapter for the IDependencyResolver, mainly because this was the common practice with all DI containers. I partly regret this decision, but using the SimpleInjectorDependencyResolver is now usually the easiest way of plugging in Simple Injector into Web API. We considered adding a SimpleInjectorControllerActivator as well, but this had no practical benefit for most users, while we still would had to document when to use what. So we decided to stick with the dependency resolver adapter; an adapter for the activator is easily created for anyone who needs it, as you can see.
For ASP.NET Core however, we went into a different direction, and as you can see in the documentation, the integration package actually contains a SimpleInjectorControllerActivator out of the box. In ASP.NET Core, the controller activator is the perfect interception point and due to the OWIN-like pipeline, a scope can be easily wrapped around a request. So with ASP.NET Core, the advised practice is to use the controller activator as interception point.
My application uses autofac IoC. It contains a layer that establishes connections to external applications (creating "Protocol" objects) - Therefore, I realized from my previous question that I should use autofac factory:
Autofac resolve in deep layer
I have a side project that includes all the autofac nugets and dlls. This one provides specific API which I use to register types in my application:
RegisterType
RegisterTypeAndAutowireProperties
RegisterConfigurationObject
RegisterInstance
BuildContainer
UpdateContainer
I believe this API is generic and fits for any application that will want to make use of IoC container.
My problem is with the factories. For example in my current application I need a factory for protocols (which are keyed and depend on many keyed services as well). Each protocol object is taking different kind and number of services and therefore I don't have a way other than making an explicit method for each protocol registration if I'm correct.
Now what happens in the next application that'll want to use this IoC API? It might not have the protocols this application contains, a case which will force me to update the IoC API for each application. Is there a way to keep my IoC wrapper generic - make it fit for any application no matter that types it contains? If you have any ideas in mind please share them with me!
Thank you
Edit:
I'll try to make it clearer, I use Autofac only. This "wrapper" is a project with the references to autofac that supplies basic API of IoC. For now I use this project only in application1.
But If tomorrow I start developing application2 I want to use this same wrapper. Therefore I can't have factories in my wrapper project that fit for a specific application. This is my issue
The short question is:
Given a library warrants using a particular IOC container for its internals, when an application consumes that library, given the app warrants using an IOC container for wiring its dependencies, given if the the two containers are different, how can they play well together?
The scenario is, the application has classes defined that depend on types from the library. So when the application container attempts to build such a class, it needs to know how to resolve the type that lives in the library.
Here's the long winded question:
This question does seem to have been asked in different shapes and form before on SO, but I can't seem to find the answer I need so I am going to have a go at it with a hypothetical _over_simplified_ concrete example.
We want to write a library for logging that users can include as a package in their solution to get logging functionality out of the box.
The public interfaces the library exposes are..
public interface ILogger {}
public interface ITarget {}
Concrete implementations are
internal class Logger: ILogger { public Logger(ITarget target) {}}
internal class FileTarget : ITarget {}
Requirements are if the user includes our package and defines a class with a property of type ILogger or has a ctor argument of type ILogger then our library is responsible for injecting a concrete implementation for that interface into the user defined class. By default that injected logger will go to the file system for logging because the default implementation of an ITarget injected into the ILogger implementation is a FileTarget by our library.
If the user decides to write a class implementing the ITarget interface then our library will use that to inject into the Logger class and not use its default FileTarget implementation.
SO what I wish to demonstrate, is their is a bi-directional dependency here.
Our library depends on the user's assemblies, since it needs to scan the user's assemblies to load any extension points (i.e. an ITarget implementation) and inject those into its own objects ahead of any default implementations.
The user's assemblies depends on the library, since if the user chooses to define a class with an ILogger interface as a dependency, then that user object should get a concrete reference to that interface provided at runtime by our library.
The easy solution is if the user and our library are both using the same IOC container, then problem is solved. But this is a strong assumption. What I wish to do is
Use an IOC container with the library that caters best to the library's requirement, in my case its Ninject.
At run time somehow provide a mechanism for the user to call via some API into my library that will ensure Ninject is fired up and it scans the user's assemblies, and wires everything taking into account all extension points.
So far so good, its perfectly achievable, but here comes the tricky part.
if the user is also using Ninject, then problem automatically solved, since Ninject already knows how to resolve Interfaces living in our library. But what if the user decides to use his/her choice of IOC container?
I almost want to define some sort of child container functionality in the library with an interface like such
public interface IDependencyResolvingModule { T Get<T>(); []T GetAll<T>(); }
and provide an implementation that uses our library's choice of container (i.e. Ninect) to resolve the type requested in the two methods define above.
I want the user's IOC container to have some functionality where if it can't resolve a dependency (i.e. an ILogger), it should hook into the IDependencyResolvingModule implementation and ask for the dependency.
This way our library gets to use its choice of IOC Container, and the user's code has a way to resolve dependencies that its IOC container has no clue about. Wouldn't this solution work if IOC containers out there some how provided functionality to register singleton instances of any IDependencyResolverModules found in assemblies in the executing assembly's dir and when they can't resolve a type, ask any of the singleton modules?
But barring a solution that requires every other IOC container to accommodate, how else can this be solved? SO the problem in a few lines is, when a third party assembly chooses to use an IOC container for its internals, what is an easy solution such that this library can simply provide a mechanism for an IOC container sitting outside to hook into and resolve dependencies that live in the library.
I see few possible approaches here:
Write default registrator for all of the popular IoC containers. Each of them should be placed in the separate assembly. Then developer can choose the one he needs and configure his container with it.
Define your own factory abstraction and write default implementation that will return the default logger. Let developer to substitute implementation of that factory. For example, with adapter for his favorite container. This approach is most container-agnostic, because developer can just use the default factory implementation. But this way has nothing to do with auto-wiring.
The lazy variation of the first approach. Write small manual about configuring a container to work with default implementations. Then developer could configure the container himself.
Combine all previous solutions to satisfy every developer. :)
EDIT: added example of integration of two containers
var allPublicInterfacesFromLibrary = typeof(AnyLibraryType)
.Assembly.GetTypes()
.Where(t => t.IsInterface && t.IsPublic);
foreach (var libraryInterface in allPublicInterfacesFromLibrary)
{
var local = libraryInterface; //to prevent closure
applicationContainer.Register(
Component.For(libraryInterface)
//delegate resolving
.UsingFactoryMethod(k => libraryContainer.Resolve(local))
//delegate lifetime management
.LifestyleTransient()
);
}