What exactly are the steps to auto inject Func<T>? - c#

I'm trying to set up a service class where I would like to inject a simple Func<OtherService> factory method in its constructor. Type OtherService is a class, which should be self-bound (and is indeed when I inject it without factory).
I've installed the latest Ninject core, and Ninject.Extensions.Factory NuGet packages. When I try to retrieve an instance from Ninject, I get an activation exception about not being able to activate IntPtr.
What am I doing wrong? If I understand correctly the documentation of the Factory extension, this type of Func binding should be automatic, without any configuration. Do I need to register the Factory extension anywhere, or create an explicit binding for OtherService? Any tips would be appreciated.
EDIT:
I have Ninject and Ninject.Extensions.Factory installed in a small separate project, where I do some customizations on Ninject. These are the following:
Kernel.Components.Add<IInjectionHeuristic, CustomInjectionHeuristic>();
Kernel.Components.Add<IActivationStrategy, TransientDisposableActivationStrategy>();
where the two custom handlers are for letting me use my custom [Service] attribute for indicating property injection, and for handling disposing of components which use my own IDisposableEx interface (with Disposed notification) for Ninject cache fine tuning.
public class CustomInjectionHeuristic : NinjectComponent, IInjectionHeuristic, INinjectComponent, IDisposable
{
public bool ShouldInject(MemberInfo member)
{
return member.IsDefined(typeof(ServiceAttribute), true);
}
}
public class TransientDisposableActivationStrategy : ActivationStrategy
{
public override void Activate(IContext context, InstanceReference reference)
{
var scope = context.GetScope();
// care about only transient scoped objects
if (scope != null) return;
if (reference.Instance is Component)
reference.Instance.As<Component>().Disposed +=
(sender, args) => context.Kernel.Components.Get<ICache>().Clear(sender);
if (reference.Instance is IDisposableEx)
reference.Instance.As<IDisposableEx>().Disposed +=
(sender, args) => context.Kernel.Components.Get<ICache>().Clear(sender);
}
}
And I also use the Ninject.Extensions.NamedScope extension for InCallScope() bindings.
Any of these customizations could have effect on proper work of the factory?
EDIT2:
I think I got it. The problem seems to be that I have to reference the Factory extension in my startup project, where I define bindings, and not in the class library where I have my basic Ninject setup. So the key is that I have to reference any binding-related extension in that project where I define the bindings. Anyway, sounds logical...

The problem seems to be that I have to reference the Factory extension in my startup project, where I define bindings, and not in the class library where I have my basic Ninject setup. So the key is that I have to reference any binding-related extension in that project where I define the bindings. Anyway, sounds logical...

Related

Simple Injector explicit attribute injection - property is null inside constructor

New to Simple Injector, trying to get some pieces working for a prototype. I am creating a WPF application that uses Simple Injector and ReactiveUI, but can't seem to get explicit property injection via attribute to trigger. The specific example I am working through is just testing injection of a logger. The plan is to roll this into a decorator, but I have run across the need for attribute injection with previous projects/DI libraries. Just want to verify I am able to use it.
Snippet of the bootstrapping:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
// Container initialization that must precede dependency registration
// occurs here
// Enable property injection via the [Import] attribute
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
SimpleInjectorInitializer initializer = new SimpleInjectorInitializer();
Locator.SetLocator(initializer);
Locator.CurrentMutable.InitializeSplat();
Locator.CurrentMutable.InitializeReactiveUI();
container.UseSimpleInjectorDependencyResolver(initializer);
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
container.Register<MainWindow>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
An instance of the System is requested from the DI container in the static RunApplication called from Main:
var system = container.GetInstance<ISystem>();
And here is the property injection in the system:
public class System : ISystem
{
[Import] public ILogger Logger { get; set; }
public System()
{
// Logger is null here. NullReferenceException is thrown
Logger.LogInfo("Creating System");
}
}
At this point in the constructor, the Logger property is null and attempt to log fails with exception. I should mention the ILogger is my own abstraction of NLog. If I instead perform constructor injection:
public System(ILogger logger)
Simple Injector picks up on this and resolves the dependency fine. I have tried changing the Import attribute to a different custom-defined Dependency attribute, no change. Have also tried just instantiating the logger as a singleton, same behavior.
Really appreciate any ideas, I'm running dry on searching forums, the SimpleInjector/ReactiveUI docs, and Steven's DI book.
Edit - here is the PropertySelectionBehavior code as well:
public class PropertySelectionBehavior<T> : IPropertySelectionBehavior
where T : Attribute
{
public bool SelectProperty(
Type implementationType, PropertyInfo propertyInfo) =>
propertyInfo.GetCustomAttributes(typeof(T)).Any();
}
public class ImportPropertySelectionBehavior :
PropertySelectionBehavior<ImportAttribute> { }
2nd Edit - I can take out all of the initialization related to ReactiveUI and still reproduce same behavior. New sample looks like:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
// Logger registration
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
// UI registration
container.Register<MainWindow>();
//container.Register<MainWindowViewModel>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
You are using the Logger property from inside System's constructor. Properties, however, are only initialized after the constructor finished. If you remove Simple Injector from the equation, and fallback to plain old C#, you would see the same. For instance:
var system = new System() // <-- constructor call
{
Logger = new NLogLogger<System>() // Logger_set is called after the ctor
};
If you run this code, you will see the same NullReferenceException thrown by the constructor of System.
What this means is that you shouldn't use any properties from inside your constructor. Even more broadly, from a DI perspective, you shouldn't use any service inside your constructor (or during construction for that matter) as is described by Mark Seemann here.
Update, the explicit property injection is working fine. It occurs after construction. I imagine there are design reasons for this, although somehow it was contrary to my mental model that the property injection would be performed on-demand/on first use.
Planning on experimenting a bit more to see what control is available over the timing to resolve property dependencies. If anyone who is more experienced has any advice on that or can point me to additional documentation I would welcome it. The decorator sounds like the more elegant way to make sure the logger is available as expected and allow independent lazy loading of decoratee concerns. Some discussion here:
SimpleInjector - "Lazy" Instantiate a singleton that has dependencies on first use

How to instantiate outside of a constructor?

How to replicate this code with Autofac syntax?
public static class MenuConfig
{
public static void Initialize()
{
var _menuService = DependecyFactory.GetInstance<IMenuService>();
Parameters.Menu = _menuService.Menu();
}
}
Before calling this a "duplicate question" please note that I'm looking for an Autofac command. I CANNOT inject the interface anywhere and then call "Resolve". What I need to is perform an "InstancePerRequest" inline and uninjected so I don't have to do this:
var _service = new Service(new Dependency(new context()));
LightInject has a method that allows instantiation from an interface OUTSIDE of a constructor like this:
var _service = DependecyFactory.GetInstance<IService>();
What is the equivalent method for Autofac?
When calling containerBuilder.Build() you get back a container which implements IContainer and ILifetimeScope, whenever you get hold of one of these interfaces, you can resolve types from it:
container.Resolve<IService>();
If you want this container to be static, you could add the container as a static property to the Program or Startup class (depending if you're creating a Console or ASP.NET application).
Remember that the root container will be around for the entire duration of your application, so this can result in unwanted memory leaks when used incorrectly. Also see the warning in the documentation.
Still, it's perfectly possible to do the memory management yourself by resolving an Owned<> version from your interface:
using (var service = Program.Container.Resolve<Owned<IService>>())
{
service.Value.UseService();
}
Anyway, since you mention a static class in the comments, the best solution is to change that into a non-static class and register it as a singleton with Autofac. Then you can inject a Func<Owned<IService>> serviceFactory into that singleton and create/dispose an instance of the service wherever you need it.
using (var service = serviceFactory())
{
service.Value.UseService();
}
This is simply not possible with Autofac. All other solutions involving Autofac will require code refactoring which may potentially break software functionality. So unfortunately, the most elegant and least disruptive solution is this:
var _service = new Service(new Dependency(new context()));
Since this is an edge case addressing only one part of the software, this compromise is acceptable. It would be nice, however, if Autofac implemented this functionality in some future release.

Can't inject a delegate using ASP.NET Core DI

Say I've a MVC Core Controller like this:
public class SomeController
{
public SomeController(IConfiguration appConfig, Func<string> someDelegate)
{
}
}
Also, I'm using AutoFac to resolve injections. Object injections are working flawlessly while adding a delegate injection produces an ASP.NET Core exception which tells that Func<string> can't be injected because there's no component to inject with such type.
When I try to manually resolve SomeController using AutoFac I get the desired behavior.
Is there any way to support this scenario without using AutoFac to resolve controllers?
Controllers are not resolved via DI by default, they are constructed in the DefaultControllerFactory or so.
Update
Microsoft.Extensions.DependencyInjection doesn't support named components, discovery, auto registrations, decorators etc.
It's meant to be simple out of the box IoC and provide the base for DI for basic applications and offer easy way for 3rd party IoC containers (with advanced features such as auto discovery, decorators etc.) to be integrated (basically all they need is process the information in IServiceCollection and return their own implementation of IServiceProvider from Configure method).
Tag helpers, controllers and view components are different in this aspect as they have their own activators (the default one use activation utilities, which at some point further down the pipeline use the service provider). For that reasons AddControllersAsServices exists, because it replaces DefaultControllerActivator (which uses ActivationUtilities, see DefaultControllerActivator.cs) with ServiceBasedActivator (which uses IServiceProvider, see ServiceBasedControllerActivator).
Also see this related answer for details on how to resolve controllers, tag helpers and view components via DI.
var builder = services
.AddMvc()
.AddControllersAsServices() // this one for your case
.AddViewComponentsAsServices()
.AddTagHelpersAsServices();
I was just run into this issue myself so I thought I would share for future reference as I had one case where I wanted to resolve a delegate but including an additional library seemed like overkill.
Given the following defintions:
public interface ISomething { /*...*/ };
public interface ISomeService { /*...*/ }
public class SomeService : ISomeService { /*...*/ }
public class Something
{
public Something(ISomeService service, string key) { /*...*/ }
}
// I prefer using a delegate for readability but you
// don't have to use one
public delegate ISomething CreateSomething(string key);
The delegate can be registered like this:
var builder = services
.AddSingleton<ISomeService, SomeService>()
.AddTrasient<CreateSomething>(provider => key => new Something(provider.GetRequiredService<ISomeService>(), key));

Setting up dependency injection for my own classes

I have a little problem I can't wrap my head around in relation to Dependency Injections. I learned how to inject dependency for .net mvc 5 controllers using Ninject. However, I can't figure out how to inject dependencies for my own classes.
For example I have a Resource class.
public class Resource
{
public IResourceLoader ResourceLoader {get;set}
public Resource(IResourceLoader ResourceLoader)
{
this.ResourceLoader = ResourceLoader;
}
}
Where IResourceLoader can be implemented to load different types of resources such as XMLLoader. So is it possible to use Ninject to automatically send an instance of XMLLoader when I do
Resource xmlResource = new Resource(/*do something here/*);
Or better yet if I have a Banner class that inherits from Resource that sets a string resourceType to "xml" and have Ninject filter instances based on that string.
Do I have to implement a factory pattern and do it myself.
Thanks
The simple use of DI is where you first register your dependencies (Ninject calls this 'type bindings'):
Bind<IResourceLoader>().To<XMLLoader>();
You can then get an instance of Resource by doing:
IKernel kernel = new StandardKernel();
var resource = kernel.Get<Resource>();
and Ninject will wire-up the constructor types it knows about.
Alternatively, there are several other ways to create dependencies, including, for example the ability to completely control parameters used to create the resource instance:
Bind<IResourceLoader>().ToMethod(context => new XMLResourceLoader("schema.xsd"));
Contextual binding
Ninject also supports something it calls Contextual Binding, where basically you can do something like this:
Bind<IResourceLoader>().To<SimpleResourceLoader>();
Bind<IResourceLoader>().To<XMLResourceLoader>().Named("XML");
public class Banner : Resource
{
public Banner([Named("XML")] IResourceLoader resourceLoader)
: base(resourceLoader) { }
}
If you're using Ninject, and in a web project, you should have a NinjectWebCommon.cs class in the App_Start folder?
In the RegisterServicesmethod you could add:
kernel
.Bind<IResourceLoader>()
.ToMethod<IResourceLoader>(InstantiateResourceLoader)
And then in the same class, implement the method like so:
private static IResourceLoader InstantiateResourceLoader(IContext ctx) {
// Put in whatever logic you need to decide on which loader you want to return
// Use ctx.Kernel.Get<WhatEver>() if you need something from the DI
return new XMLLoader();
}

Resolving AutoFac dependencies inside Module class

I'm new to AutoFac and am currently using custom modules inside my app config to boot up some core F# systems. The code I'm using is
var builder = new ContainerBuilder();
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
builder.Build();
And inside my app config I have the appropriate logic to start up the relevant systems. I would like to have access to the DefaultLogger inside my Modules. Metadata for the Module base class has the following options available to me:
protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration);
protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource);
public void Configure(IComponentRegistry componentRegistry);
protected virtual void Load(ContainerBuilder builder);
I've only been using Load so far and I can't see any methods on the builder that would allow me to get at the logging service.
When registering something within your modules with autofac instead of using RegisterType method you might use Register method:
builder.Register(c =>
{
IComponentContext ctx = c.Resolve<IComponentContext();
IDefaultLogger logger = ctx.Resolve<IDefaultLogger>();
...do something with logger...
return ...return object you want to register...;
});
The answer turned out to be incredibly simple. I just added IComponentContext as a dependency to my Module's implementation
public class LocalActorSystemModule : Module {
private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module
public LocalActorSystemModule(IComponentContext componentContext) {
m_ComponentContext = componentContext;
}
And let AutoFac inject the IComponentContext for me. That way I can resolve any dependencies I require inside the module.
Rule of thumb for using every IoC/DI Container: Resolve once! => then you get all dependencies resolved for your requested object. If you try to resolve multiple times, register other objects (in the meantime) you're stuck in hell. Really. If you want to retrieve objects for different purposes at different places and time points (resolved from central registration) you may be looking for the Service Locator Pattern instead (but this is often described as an Anti-Pattern, too).
Modules have the purpose to bundle related registrations (conditionally) as statet in the Autofac documentation:
A module is a small class that can be used to bundle up a set of
related components behind a ‘facade’ to simplify configuration and
deployment.
... so if they are just a sum of registrations and the container has not yet been build you are not able to resolve and use an (even previously registered) component immediately (except calling a method on the registrant itself through OnActivate* hooks or when using instance registration, but I think this is not the case for your example). The components are just in the state of registration but the complete context is not ready for resolving. What would happen if you override the registration in another Module? Then you would have injected different objects... bad idea. Maybe you should rethink your application design and which objects have which responsibilities.
By the way: Logging is a cross cutting concern that is often "injected / resolved" by calling a separate static factory or service instead of doing constructor / property injection (see usage of Common.Logging for example).
public class MyModule : Module
{
private static readonly ILog Log = LogManager.GetLogger<MyModule>();
protected override void Load(ContainerBuilder builder)
{
Log.Debug(msg => msg("Hello")); // log whatever you want here
}
}
You can also try to use AOP libraries and weave the dependency into the Module (using reflection). But I don't think it's worth to try just for logging in a Module.
Anyway: #mr100 has already shown the right usage during registration. There you can also handle activation etc. but not do logging for the Module itself.

Categories