I was wondering how I'd go about setting up my Dependency Injection to inject a dependency into properties that have public getters and setters ({get; set}).
So, an example would be:
namespace Dexter.Services {
public class CommandHandlerService : InitializableModule {
public CommandService CommandService { get; set; }
}
}
With the following dependency injector:
namespace Dexter {
public static class InitializeDependencies {
public static async Task Main() {
ServiceCollection ServiceCollection = new();
CommandService CommandService = new();
ServiceCollection.AddSingleton(CommandService);
Assembly.GetExecutingAssembly().GetTypes()
.Where(Type => Type.IsSubclassOf(typeof(InitializableModule)) && !Type.IsAbstract)
.ToList().ForEach(
Type => ServiceCollection.TryAddSingleton(Type)
);
ServiceProvider = ServiceCollection.BuildServiceProvider();
// Initialization stuff.
}
}
}
In this example, I would like the CommandService to automatically inject into the property.
I know this is possible because Discord.NET is able to do this, and I'd love to stick with that same codestyle.
( Discord.NET: https://docs.stillu.cc/guides/commands/dependency-injection.html )
Thanks! <3
This can be done without having to swap out the default DI container (IServiceProvider) using the Quickwire NuGet package.
Simply decorate your service with the [RegisterService] attribute and add [InjectService] to the property. No need for the interface.
[RegisterService(ServiceLifetime.Singleton)]
public class CommandHandlerService {
[InjectService]
public CommandService CommandService { get; set; }
}
Now from your main function, just call ScanCurrentAssembly:
public static async Task Main() {
ServiceCollection ServiceCollection = new();
ServiceCollection.ScanCurrentAssembly();
ServiceProvider = ServiceCollection.BuildServiceProvider();
// Initialization stuff.
}
Behind the scenes, ScanCurrentAssembly does all the necessary wiring to resolve dependencies, instantiate the class and inject it into properties.
For anyone curious, as per what Panagiotis recommended, a solution to this would be to create your own dependency injection. As such, I wrote a small method that loops through all the services in the provider, and attaches public properties to it. It may have bugs! Particularly regarding scoped services, of which I haven't written for it to support, but this should work as a good starting point for someone wishing to achieve a similar result!
public static object SetClassParameters(this object newClass, IServiceScope scope, IServiceProvider sp)
{
newClass.GetType().GetProperties().ToList().ForEach(property =>
{
if (property.PropertyType == typeof(IServiceProvider))
property.SetValue(newClass, sp);
else
{
object service = scope.ServiceProvider.GetService(property.PropertyType);
if (service != null)
{
property.SetValue(newClass, service);
}
}
});
return newClass;
}
Where you can use a method like the following to inject dependencies into classes. For instance, I wished to inject them into classes that extended an abstract "event" class that I made. This can be seen below:
using (var scope = serviceProvider.CreateScope()) {
GetEvents().ForEach(
type => serviceProvider.GetRequiredService(type).SetClassParameters(scope, serviceProvider)
);
}
Where GetEvents() is a reflexive function that returns all classes extending the abstract class given.
Related
In a .NET app we have lots of classes that rely on dependency injection:
public class MyClass {
public MyClass(ILoggerFactory loggerFactory) ...
The best practice here appears to be that anything using the DI pattern should be part of the DI services too.
So, rather than calling GetService<ILoggerFactory> in the class we'd use [FromServices], and to register it we need to add it to Program.cs or Startup.cs:
builder.Services.AddTransient<MyClass>();
Which is fine for a few, but we now have a lot of these and it feels like technical debt to hand-maintain a long list of classes.
builder.Services
.AddTransient<MyClass>()
.AddTransient<MyClass2>()
.AddTransient<MyClass3>()
...
.AddTransient<MyClass150>();
I have a workaround, which looks like this:
[AttributeUsage(AttributeTargets.Class)]
public sealed class RegisterServiceAttribute : Attribute
{
public ServiceLifetime Lifetime { get; }
public Type? ServiceType { get; }
public RegisterServiceAttribute(ServiceLifetime lifetime, Type? serviceType) =>
(Lifetime, ServiceType) = (lifetime, serviceType);
public RegisterServiceAttribute(ServiceLifetime lifetime) =>
(Lifetime) = (lifetime);
}
namespace Microsoft.Extensions.DependencyInjection;
public static class RegisterServiceAttributeExtensions
{
public static IServiceCollection AddServicesWithAttribute(this IServiceCollection services, Assembly assembly)
{
var typesRegisteredByAttribute =
from t in assembly.GetTypes().AsParallel()
where !t.IsAbstract
let attributes = t.GetCustomAttributes(typeof(RegisterServiceAttribute), true)
where attributes?.Length > 0
select new { ImplementationType = t, Attribute = attributes.Cast<RegisterServiceAttribute>().First() };
foreach (var regAttr in typesRegisteredByAttribute.ToArray())
services.Add(new(
regAttr.Attribute.ServiceType ?? regAttr.ImplementationType,
regAttr.ImplementationType,
regAttr.Attribute.Lifetime));
return services;
}
}
And these let us declare in the class that it should be in the DI services:
[RegisterService(ServiceLifetime.Transient)]
public class MyClass {
Then in Program.cs:
services.AddServicesWithAttribute(...get whatever assembly I expect them in);
However, all this reflection slows my application's start up, as it now needs to reflect all the types to find the 150 or so that use or inherit [RegisterService], is there a better way to flag those classes in their definition?
Implementations are messy too - they can be added:
[RegisterService(ServiceLifetime.Transient, typeof(IMyInterface))]
public class MyClass : IMyInterface {
So I can use [FromServices] IMyInterface myInterface, but if MyClass doesn't implement IMyInterface I have some nasty run time startup crashes. Ideally the compiler would know that.
This also feels like I must be reinventing the wheel - surely there is already something that does this in .NET's DI model?
If there isn't is there some good reason that they haven't implemented it that I missed?
When creating an application with Dependency Injection and it utilizes a framework for Dependency Injection such as Unity (or Ninject).
How do you initialize registering the interfaces to the container at the beginning all together and keep them available for the application to use throughout its running lifecycle of the application?
Do you need to pass the DI Container to each method that may utilize dependency injection, or is there some way to make the container globally accessible so that you can register them all together in the beginning and access them throughout running the application without having to continually pass them, and be able to utilize them when ever needed?
Environment: Visual Studio 2015, C#, Microsoft Unity (for DI Container)
Example Code
static void Main(string[] args)
{
// Make Unity resolve the interface, providing an instance
// of TrivialPursuit class
var diContainer = new UnityContainer();
diContainer.RegisterType<IGame, TrivialPursuit>();
var gameInstance = diContainer.Resolve<IGame>();
var xotherClass = new AnotherClass();
xotherClass.TestOtherClassOtherMethod();
}
------ Another class without context of the Dependency Injection Class ------
public void TestOtherClassOtherMethod()
{
IGame gameInstance = -- -Container is Not available to resolve from in this class ---
}
Reason: I don't want to need to pass every possible type that I may need later on to each class I load up, I will just want to use the instances when I need them. The more deeper I get into classes, later as the application becomes more complex, I won't want to pass down instances for each type up from the Main() method to each class.
A Dependency Injection (DI) container is just that. A framework for facilitating DI. You don't pass the container around in order to resolve instances of objects. You just request the type you need in your classes constructor and the DI framework will inject the appropriate dependency.
Mark Seemann has written a good book on dependency injection that I would recommend.
You register everything that'll need to be resolved with the container in the composition root. That is to say when your program starts up is when everything should be registered.
Let's say we have the following code:
public class MyClass
{
public Run()
{
var dependency = new Dependency1();
dependency.DoSomething();
}
}
public class Dependency1
{
public void DoSomething()
{
var dependency = new Dependency2();
dependeny.DoSomethingElse();
}
}
public class Dependency2
{
public void DoSomethingElse()
{
}
}
This gives us the above dependency chain: MyClass -> Dependency1 -> Dependency2.
The first thing we should do is refactor the classes to take their dependencies through their constructor and rely on interfaces rather than concretions. We can't inject dependencies unless there is a place to inject them (constructor, property, etc).
Here is the refactored code:
public interface IMyClass
{
void Run();
}
public interface IDependency1
{
void DoSomething();
}
public interface IDependency2
{
void DoSomethingElse();
}
public class MyClass : IMyClass
{
public readonly IDependency1 dep;
public MyClass(IDependency1 dep)
{
this.dep = dep;
}
public void Run()
{
this.dep.DoSomething();
}
}
public class Dependency1 : IDependency1
{
public readonly IDependency2 dep;
public MyClass(IDependency2 dep)
{
this.dep = dep;
}
public void DoSomething()
{
this.dep.DoSomethingElse();
}
}
public class Dependency2 : IDependency2
{
public void DoSomethingElse()
{
}
}
You'll notice the classes now all take their dependencies through their constructors and do not new up anything. Classes should only take in dependencies that they actually need. For example, MyClass does not NEED a Dependency2 so it doesn't ask for one. It only asks for a Dependency1 because that's all it needs. Dependency1 NEEDS Dependency2, not MyClass.
Now to wire it all up WITHOUT a container we would just new it all up in the composition root:
void Main()
{
var myClass = new MyClass(new Dependency1(new Dependency2()));
}
You can see how that could get cumbersom if we had tons of classes and depdencies. That's why we use a container. It handles all the depdency graph for us. With a container we'd rewrite it as follows:
void Main()
{
// the order of our registration does not matter.
var container = new Container();
container.Register<IDependency1>.For<Dependency1>();
container.Register<IDependency2>.For<Dependency2>();
container.Register<IMyClass>.For<MyClass>();
// then we request our first object like in the first example (MyClass);
var myClass = container.Resolve<IMyClass>();
myClass.Run();
}
In the second example the container will handle wiring up all the dependencies. So we never need to pass Depedency2 to MyClass and then to Depedency1. We only need to request it in Dependency1 and the container will wire it up for us like in the first example.
So in your example we would rewrite it like so:
static void Main(string[] args)
{
var game = new UnityContainer();
game.RegisterType<IGame, TrivialPursuit>();
game.RegisterType<IAnotherClass, AnotherClass>();
game.RegisterType<IYetAnotherClass, YetAnotherClass>();
var gameInstance = game.Resolve<IGame>();
// you'll need to perform some action on gameInstance now, like gameInstance.RunGame() or whatever.
}
public class Game : IGame
{
public Game(IAnotherClass anotherClass)
{
}
}
public class AnotherClass : IAnotherClass
{
public AnotherClass(IYetAnotherClass yetAnotherClass)
{
}
}
public class YetAnotherClass : IYetAnotherClass {}
In these cases there is no need to pass the container around. You register your dependencies with the container then request them in your classes constructors. If you wish to use the container in the class WITHOUT requesting it through the constructor then you are not doing DI you are just using the container as a singleton service locator. Something that should generally be avoided.
Container as a Service Locator
This should be generally avoided but if you want to use the container as a service locator you have two options:
1) Pass the container into your classes that need it through the constructor.
You can use the above examples for wiring your classes up for DI. But instead of requesting a dependency like IDependency in the constructor you just pass the container.
public class Game : IGame
{
public Game(IContainer container)
{
var blah = container.Resolve<IBlah>();
}
}
2) Request your container through a static class:
public static class ServiceLocator
{
private static IContainer container;
public static IContainer Container
{
get
{
if (container == null)
{
container = new Container();
}
return container;
}
}
}
Register everything as normal in your composition root using the ServiceLocator class. Then to use:
public class MyClass
{
public void DoSomething()
{
var blah = ServiceLocator.Container.Resolve<IBlah>();
}
}
Shortly speaking I am trying to link Castle Windsor container with Unitycontainer. Let me explain the context:
I have a project in which for very long time it used castle windsor. A few days ago, I got a bunch of dll's that I must consume / use from my old project. Those DLL's use Unity Container as their injection mechanism. I also have access to interfaces / implementations that are found in those dlls but I would not try to instantiate manually implementations but I would just prefer, if possible, to link the Unity container with my current castle windsor container. How could I achieve this?
So if I have:
public class MyService: IService
{
public MyService (IThidPartyService thirdParty)
{
}
}
If I resolve IService with windsor it would be nice that IThirdPartyService to be solved by the other container: Unity.
Thank you!.
I think this is a perfect example for the use of a custom ISubDependencyResolver. Whenever Castle won't know how to resolve a specific dependency it will address that custom resolver. That new resolver will depend on the Unity Container and will use it to resolve "for" Castle.
Castle's documentation states that:
If previous places weren't able to resolve the dependency resolver
will ask each of its sub resolvers (ISubDependencyResolver) if they
can provide the dependency.
So when that dependency will not be found in Castle it will seek your new resolver which will provide the dependency.
Here is a working example with both Constructor Injection and Property Injection:
class Program
{
static void Main(string[] args)
{
var unityContainer = new UnityContainer();
unityContainer.RegisterType<IDependency, Dependency1>();
unityContainer.RegisterType<IPropertyDependency, PropertyDependency1>();
WindsorContainer castleContainer = new WindsorContainer();
castleContainer.Kernel.Resolver.AddSubResolver(new UnityResolver(unityContainer));
castleContainer.Register(
Component.For<SomeType>());
var result = castleContainer.Resolve<SomeType>();
}
}
public interface IDependency { void Foo(); }
public class Dependency1 : IDependency { public void Foo() { } }
public interface IPropertyDependency { }
public class PropertyDependency1 : IPropertyDependency { }
public class SomeType
{
public SomeType(IDependency dependency) { ConstructorDependency = dependency; }
public IDependency ConstructorDependency { get; private set; }
public IPropertyDependency PropertyDependency { get; set; }
}
public class UnityResolver : ISubDependencyResolver
{
public UnityResolver(UnityContainer container)
{
Container = container;
}
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return Container.Registrations.Any(z => z.RegisteredType.Equals(dependency.TargetType));
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return Container.Resolve(dependency.TargetType);
}
public UnityContainer Container { get; set; }
}
And the result:
As for the code for checking Unity for the CanResolve - I'm sure it can be improved - I do not know much about Unity
I'm taking a stab at properly implementing DI in my Xamarin Android application using Autofac but I'm having issues understanding how I should handle instantiating objects that require data passed into their constructor. For example one of our viewmodels needs a string and a guid passed in to its constructor. Something that looks promising is Delegate Functions offered by Autofac. This is where the line between Service Locator and DI appears to blur, at least in my mind. In order to use the Delegate Functions you must call container.Resolve, or rather it's recommended to use the IComponentContext.Resolve. Many blogs recommend not using Resolve outside of the bootstapper/main entry point. Is there something I am missing here? Is there a better way to create objects using DI? I am familiar with the Factory pattern to create objects but I feel that I'm losing the benefits of DI going that route since I am back to manually passing in services/objects to the newly created object. Thanks for any feedback!
It is not recommended to call container.Resolve() to use a delegate factory. The correct way is shown on the delegate factories page that you already linked to:
public class Portfolio
{
Shareholding.Factory ShareholdingFactory { get; set; }
IList<Shareholding> _holdings = new List<Shareholding>();
public Portfolio(Shareholding.Factory shareholdingFactory)
{
ShareholdingFactory = shareholdingFactory;
}
public void Add(string symbol, uint holding)
{
_holdings.Add(ShareholdingFactory(symbol, holding));
}
}
When the docs show an explicit call to container.Resolve() you should realize that they are not showing best practice, they are simply proving that it can be resolved without coding up a whole new class (like Portfolio) to consume it.
In order to use the Delegate Functions you must call container.Resolve
No, at least not in this case.
Assuming you have registered Shareholding. Now you can ask a dependency on Func<Shareholding>, ie. something hat returns a Shareholding when you call it.
But as the Shareholding constructor has two parameters, it cannot be resolved without supplying those parameters. Just add them to the declaration like this: Func<string, uint, Shareholding>. Now you can resolve the dependency when you supply those parameters.
Here is a better example.
I recently (yesterday) faced the same problem I wound up using the ServiceClient object you see in the code below. This object addresses your question about using the container outside of the bootstrapper. I have read arguments that say not to pass the container around and I think they are mostly valid. In my case however the ServiceClient class represents a single point of entry into my service layer so I thought it was appropriate to pass the container.
The way I use this at the moment is to pass an instance of ServiceClient into my BaseController:
// In Global.asax.cs
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ServiceClient>().As<IServiceClient>();
BaseController:
public abstract class BaseController<T> : Controller where T :class
{
public IServiceClient ServiceClient { get; set; }
public BaseController(IServiceClient serviceClient)
{
ServiceClient = serviceClient;
}
}
In my controller I can resolve, instantiate, and call a service that uses unmanaged resources with just one line like this:
myViewModel = await ServiceClient.OfType<ICustomerService>().TryAsync(x => x.GetCustomerByID(id));
ServiceClient:
public class ServiceClient : IServiceClient
{
private IComponentContext _container;
public ServiceClient(IComponentContext container)
{
_container = container;
}
public ServiceCallWrapper<T> OfType<T>() where T : class, IDisposable
{
return new ServiceCallWrapper<T>(_container);
}
}
public class ServiceCallWrapper<T> : IServiceCallWrapper<T> where T : class, IDisposable
{
private IComponentContext _container;
internal ServiceCallWrapper(IComponentContext container)
{
_container = container;
}
public void Try(Action<T> method)
{
// consider try/catch/log/throw here
using (T client = _container.Resolve<T>())
{
method(client);
}
}
public TResult Try<TResult>(Func<T, TResult> method)
{
using (T client = _container.Resolve<T>())
{
return method(client);
}
}
public async Task TryAsync(Func<T, Task> method)
{
using (T client = _container.Resolve<T>())
{
await method(client);
}
}
public async Task<TResult> TryAsync<TResult>(Func<T, Task<TResult>> method)
{
using (T client = _container.Resolve<T>())
{
return await method(client);
}
}
}
In a Console application, I'm using Log4Net and in the Main method I'm getting the logger object. Now, I'd like to make this log object available in all my classes by letting all the classes inherit from a BaseClass which has a ILog property and is supposed to be set by Property Injection rather than Constructor Injection.
I'm using AutoFac IoC container, how to inject my log Object to the Log property of my every class?
What's the best/easiest way to achieve this?
Is there any way to automatically resolve types?
Below is my test application:
namespace ConsoleApplication1
{
class Program
{
static ILog Log;
static IContainer Container;
static void Main(string[] args)
{
InitializeLogger();
InitializeAutoFac();
// the below works but could it be done automatically (without specifying the name of each class)?
Product.Log = Container.Resolve<ILog>();
// tried below but didn't inject ILog object into the Product
Container.Resolve<Product>();
RunTest();
Console.ReadLine();
}
private static void RunTest()
{
var product = new Product();
product.Do();
}
private static void InitializeAutoFac()
{
var builder = new ContainerBuilder();
builder.Register(c => Log).As<ILog>();
builder.RegisterType<Product>().PropertiesAutowired();
Container = builder.Build();
}
private static void InitializeLogger()
{
log4net.Config.XmlConfigurator.Configure();
Log = LogManager.GetLogger("LoggerName");
}
}
public class Product
{
public static ILog Log { get; set; }
public void Do()
{
// this throws exception because Log is not set
Log.Debug("some Debug");
}
}
}
In my opinion the solution Ninject created is much nicer than the propertyinjection in Autofac. Therefore I created a a custom attribute which is a postsharp aspect which automatically injects my classes:
[AutofacResolve]
public IStorageManager StorageManager { get; set; }
My aspect:
[Serializable]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class AutofacResolveAttribute : LocationInterceptionAspect
{
public override void OnGetValue(LocationInterceptionArgs args)
{
args.ProceedGetValue();
if (!args.Location.LocationType.IsInterface) return;
if ( args.Value != null )
{
args.Value = DependencyResolver.Current.GetService(args.Location.LocationType);
args.ProceedSetValue();
}
}
}
I know the answer on the question is already given but I thought this was a really neat way of solving automatic property injection in Autofac. Maybe it'll be useful to somebody in the future.
Use Property Injection:
builder.Register(c => LogManager.GetLogger("LoggerName"))
.As<ILog>();
builder.RegisterType<CustomClass>()
.PropertiesAutowired();
Property injection works for Properties and not for Fields. In your class, Log is a field and not a property and hence it will never get resolved by the Autofac.
I didn't want to use postsharp so I made a quick solution, but it doesn't auto inject. I am new to Autofac, and it should be possible to build on to this solution.
[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class AutofacResolveAttribute : Attribute
{
}
public class AutofactResolver
{
/// <summary>
/// Injecting objects into properties marked with "AutofacResolve"
/// </summary>
/// <param name="obj">Source object</param>
public static void InjectProperties(object obj)
{
var propertiesToInject = obj.GetType().GetProperties()
.Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == nameof(AutofacResolveAttribute))).ToList();
foreach (var property in propertiesToInject)
{
var objectToInject = Autofact.SharedContainer.Resolve(property.PropertyType);
property.SetValue(obj, objectToInject, null);
}
}
}
Use it with this call:
AutofactResolver.InjectProperties(sourceObject);
Use Property Injection (In addition to #cuongle answer).
Option 1:
builder.Register(c => LogManager.GetLogger("LoggerName")).As<ILog>();
builder.RegisterType<Product>()
.WithProperty("Log", LogManager.GetLogger("LoggerName"));
Option 2:
Or you can add a SetLog method to the Product class:
public class Product
{
public static ILog Log { get; set; }
public SetLog(Log log)
{
this.Log = log;
}
}
This way you won't have to call LogManager.GetLogger("LoggerName") twice but to use the context of the builder in order to resolve the Log.
builder.Register(c => LogManager.GetLogger("LoggerName")).As<ILog>();
builder.Register(c =>
var product = new Product();
product.SetLog(c.Resolve<Log>());
return product;
);
Option 3:
Use the OnActvated:
The OnActivated event is raised once a component is fully constructed.
Here you can perform application-level tasks that depend on the
component being fully constructed - these should be rare.
builder.RegisterType<Product>()
.OnActivated((IActivatedEventArgs<Log> e) =>
{
var product = e.Context.Resolve<Parent>();
e.Instance.SetParent(product);
});
These options gives more control, and you will not have to worry about #steven comment:
The scary thing with PropertiesAutowired however is that it does
implicit property injection, which means that any unresolvable
dependencies will be skipped. This makes it easy to miss configuration
errors and can result in application that fails at runtime
There is an interface IPropertySelector that you can implement and pass the implementaiton via .PropertiesAutowired(new MyPropertySelector()). This will allow you to implement any logic you want.