If I have two classes of the same interface, and a constructor that takes two different versions of it - how can I use Unity container to resolve the dependencies?
Here's a simple test:
class Dependant
{
public Dependant(ILog dbLog, ILog fsLog)
{
foreach (var i in Enumerable.Range(1, 15))
{
if (i%3 == 0)
dbLog.Log(string.Format("{0} - going to DB", i));
else
fsLog.Log(string.Format("{0} - going to FS", i));
}
}
}
Now, I'd like to use container to resolve dependencies. I tried this:
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ILog, DatabaseLogger>();
container.RegisterType<ILog, FileLogger>();
var dependant = container.Resolve<Dependant>();
}
But when the Dependant is resolved with two instances of FileLogger. I tried to give names to registration, to match the names used by the constructor but that didn't work.
You can register/resolve two implementation of the same interface using named components. For your example it would look similar to the following
var container = new UnityContainer();
container.RegisterType<ILog, DatabaseLogger>("databaseLogger");
container.RegisterType<ILog, FileLogger>("fileLogger");
container.RegisterType<Dependant>(new InjectionConstructor(
new ResolvedParameter<ILog>("databaseLogger"),
new ResolvedParameter<ILog>("fileLogger")));
var dependant = container.Resolve<Dependant>();
You can also register your database logger as the default if you leave out the naming, f.e.
container.RegisterType<ILog, DatabaseLogger>();
container.RegisterType<ILog, FileLogger>("fileLogger");
In that case resolving ILog would use your DatabaseLogger. So there's no need to define more interfaces as needed.
EDIT
I modified the code snippet above, because I think it better fits your needs.
Create a separate interface for each one -- since you are using them separately in your application anyway. They can both inherit from ILog if you need to use them polymorphically but just making two different interfaces will let Unity resolve them for your constructor.
public interface IDatabaseLog: ILog
{
}
public interface IFileLog: ILog
{
}
public class DatabaseLogger: IDatabaseLog
{
}
public class FileLogger: IFileLog
{
}
public Dependant(IDatabaseLog dbLog, IFileLog fsLog)
{
//useful code
}
Change the constructor so that you take in a array instead:
class Dependant
{
public Dependant(ILog[] logs)
{
foreach (var i in Enumerable.Range(1, 15))
{
foreach (var log in logs)
log.Log(string.Format("{0} - going to FS", i));
}
}
}
Related
Having the following interface and their implementations...
public interface IEmpty<T> { }
public class Empty1 : IEmpty<Empty1>{ }
public class Empty2 : IEmpty<Empty2>{ }
public class EmptyN : IEmpty<EmptyN>{ }
allows me to register them and inject them explicitly into constructors
public class NewClass1 {
private IEmpty<Empty1> Empty;
public NewClass1(IEmpty<Empty1> empty)
{
Empty = empty;
}
public string EmptyType => $"{Empty.GetType()}";
}
but when I tried to resolve all implementations of 'IEmpty<>' at once...
var allIEmpties = host.Services.GetServices(typeof(IEmpty<>));
allIEmpties.ToList().ForEach(empty => Console.WriteLine(empty.GetType()));
... execution of the code threw a 'NotSupportedException' (Cannot create arrays of open type), which I kind of understand, but leaves me wondering if it can be done and how it would have to be done to get a handle on all Services implementing IEmpty.
Would anyone have an idea of how to achieve this?
My motivation to get this working is to
only register each service once (DRY)
be able to explicity inject services into constructors without the need of some resolver-pattern or named dependencies
load all implementations after startup to validate specific properties they are requried to implement due to the interfaces without having to search reflectively through all assemblies, which is my temporary solution but crawling through a box of needles to find 2 specific ones sounds wrong, if I could have a sorted box offering me direct access to the needles I need...
Using these additional nuget packages:
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Hosting.Abstractions
I have created this proof of concept snippet in LinqPad, in case you'd want to have a go:
void Main()
{
var args = new List<string>();
var host = CreateHostBuilder(args.ToArray()).Build();
var newClass = host.Services.GetService<NewClass1>();
Console.WriteLine(newClass.EmptyType);
var oneEmpty = host.Services.GetService(typeof(IEmpty<Empty2>));
Console.WriteLine(oneEmpty.GetType());
var allIEmpties = host.Services.GetServices(typeof(IEmpty<>));
allIEmpties.ToList().ForEach(empty => Console.WriteLine(empty.GetType()));
}
IHostBuilder CreateHostBuilder(string[] args)
{
var hostBuilder =
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) => {
builder.SetBasePath(Directory.GetCurrentDirectory());
})
.ConfigureServices((context, services) => {
services.AddTransient<IEmpty<Empty1>, Empty1>();
services.AddTransient<IEmpty<Empty2>, Empty2>();
services.AddTransient<IEmpty<EmptyN>, EmptyN>();
services.AddTransient<NewClass1>();
});
return hostBuilder;
}
public class NewClass1 {
private IEmpty<Empty1> Empty;
public NewClass1(IEmpty<Empty1> empty)
{
Empty = empty;
}
public string EmptyType => $"{Empty.GetType()}";
}
public interface IEmpty<T> {}
public class Empty1 : IEmpty<Empty1>{ }
public class Empty2 : IEmpty<Empty2>{ }
public class EmptyN : IEmpty<EmptyN>{ }
Resolving a list of generic types based on its open-generic definition by calling GetServices(typeof(IEmpty<>)) is not supported by MS.DI. Although technically possible, there is no DI Container that I'm familiar with that actually supports this.
There are many possible ways to solve your issue. You could, for instance, introduce a non-generic IEmpty (marker) interface that IEmpty<T> inherits from.
You can also go through the code base using Reflection, as you already mentioned, or you can go through the registrations in the ServiceCollection to get all registered IEmpty<T> registrations. This list can than be used to get the list. For instance:
var emptyTypes =
from s in services
where s.ServiceType.IsGenericType
where s.ServiceType.GetGenericTypeDefinition() == typeof(IEmpty<>)
select s.ServiceType;
foreach (Type emptyType in emptyTypes)
{
var empty = host.Services.GetRequiredService(emptyType);
Console.WriteLine(empty.GetType());
}
I want to use Autofac to create a new instance of one or several WCF channels for a given unit of work. I'd like to use the command pattern to represent units of work, i.e. a given command class is injected with the channel(s) it needs and implements a bunch of related operations.
I tried the following:
interface IUnitOfWork
{
}
class FooCall : IUnitOfWork
{
readonly BarChannel _channel;
public FooCall(BarChannel channel)
{
Console.WriteLine($"FooCall({new {channel}})");
_channel = channel;
}
public string Foo()
{
return "FOO";
}
}
class BarChannel
{
public BarChannel()
{
Console.WriteLine("BarChannel()");
}
}
class FooService
{
Func<Owned<FooCall>> _helperFn;
public FooService(Func<Owned<FooCall>> helperFn)
{
_helperFn = helperFn;
}
public void CallFoo()
{
using (var helper = _helperFn())
{
Console.WriteLine($"CallFoo(), helper={helper}");
helper.Value.Foo();
}
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BarChannel>().InstancePerOwned<IUnitOfWork>();
builder.RegisterType<FooCall>().AsImplementedInterfaces().AsSelf();
builder.RegisterType<FooService>();
using (var scope = builder.Build().BeginLifetimeScope())
{
Console.WriteLine("call 1");
scope.Resolve<FooService>().CallFoo();
Console.WriteLine("call 2");
scope.Resolve<FooService>().CallFoo();
}
}
}
In short: a service method creates an owned unit of work; the unit of work is injected with a per-owned channel that it calls. The code sample should show two channel instances being created.
Except that it seems that the lifetime scope created for owned dependencies is only tagged with the type as which the dependency was resolved - i.e. as FooCall, not as IUnitOfWork. If I register BarChannel as InstancePerOwned<FooCall>, the code works; as is, registered as InstancePerOwned<IUnitOfWork>, it fails to resolve FooService since it can't find a matching lifetime scope. Am I missing something or is what I want to do not possible with Autofac? I'd rather not have to register all my WCF channels as instance-per-owned for every command class, that seems like it would get pretty verbose. Another workaround would be using instance-per-depedency and resolving a Func directly, but that won't let me say compose units of work while reusing channels and their dependencies between them.
The problem is that InstancePerOwned<T> is really just a special case of InstancePerMatchingLifetimeScope(params object[] lifetimeScopeTag), where the scope is tagged with something like typeof(T). As it stands, there needs to be a direct link between the tag provided there and the one attached to the scope when attempting to resolve, which is always set to the type of whatever's inside that specific Owned<> dependency. There's no additional logic to imply relations between types at that point, it's just a direct match on the tags.
However, InstancePerMatchingLifetimeScope does allow multiple tags to be specified, so it's possible to do something like:
builder.RegisterType<BarChannel>()
.InstancePerMatchingLifetimeScope(new TypedService(typeof(FooCall)),new TypedService(typeof(AnotherUnitOfWork)));
To wrap this up a bit more neatly you could use:
private static IEnumerable<Type> GetTypesImplementingInterface<TInterface>()
{
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(TInterface).IsAssignableFrom(p));
}
and then a new extension method:
public static class AutofacRegistrationBuilderExtensions
{
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerOwned<TLimit, TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, IEnumerable<Type> serviceTypes)
{
return builder.InstancePerMatchingLifetimeScope(serviceTypes.Select(s => new TypedService(s)).ToArray());
}
}
The usage would then just be:
builder.RegisterType<BarChannel>().InstancePerOwned(GetTypesImplementingInterface<IUnitOfWork>());
I'm not sure if the last part there would be worth pulling into Autofac itself, but I guess if it did then it might be better to combine the two methods above together and retrieve the list of types applicable from existing registrations, e.g. something like
InstancePerOwnedImplementing<TInterface>();
Alternatively, it would probably be a bit messy to extend the matching scope logic to check the relationship between types at resolution time, since not all tags are of the type Type.
Let's assume I have interfaces like the following:
public interface ISomething { };
public interface IResolver
{
string ResolveBy(ISomething something);
}
Now I have two resolver types; one that delivers the best solution, but has a chance to fail and one resolver, that does always return a solution, which should act as a fallback strategy:
public class UnsafeResolver : IResolver
{
Random random = new Random();
public string ResolveBy(ISomething something)
{
if (random.NextDouble() > 0.5)
{
return "best solution ever!";
}
else
{
throw new InvalidOperationException("something went wrong...");
}
}
}
public class SafeResolver : IResolver
{
public string ResolveBy(ISomething something)
{
return "fallback solution";
}
}
Now I want to combine both resolver within a safeguarded composition decorator:
public class SafeguardedResolver : IResolver
{
private readonly IResolver unsafeResolver;
private readonly IResolver safeResolver;
// This is the problem with Ninject: Two parameters with same interface...
public SafeguardedResolver(IResolver unsafeResolver, IResolver safeResolver)
{
// guards omitted!
this.unsafeResolver = unsafeResolver;
this.safeResolver = safeResolver;
}
public string ResolveBy(ISomething something)
{
try
{
return unsafeResolver.ResolveBy(something);
}
catch (InvalidOperationException)
{
return safeResolver.ResolveBy(something);
}
}
}
So my question is: How can I realize the binding with Ninject without using Named Binding Strategies? I do not want any dependencies to the container in my domain classes, so the proposed solution does not work for me 😞
And of course without changing the ctor to IEnumerable<IResolver> - I want two separate clearly named parameters!
Why is it not possible to define the binding via the names of the parameters? For example something like this:
Bind<IResolver>().To<SafeguardedResolver>();
Bind<IResolver>().To<UnsafeResolver>()
.WhenInjectedInto<SafeguardedResolver>()
.AsParameter("unsafeResolver");
Bind<IResolver>().To<SafeResolver>()
.WhenInjectedInto<SafeguardedResolver>()
.AsParameter("safeResolver");
Isn't it possible to get the names of a parameter with reflection?
I hope somebody can give me an answer, how to solve that (perhaps by using another DI framework?) or why this is impossible.
I do not want any dependencies to the container in my domain classes
You can use named bindings without referencing the container from your class library, here is how you can do it:
StandardKernel kernel = new StandardKernel();
kernel
.Bind<IResolver>()
.To<SafeguardedResolver>()
.WithConstructorArgument("unsafeResolver", c => c.Kernel.Get<IResolver>("unsafe"))
.WithConstructorArgument("safeResolver", c => c.Kernel.Get<IResolver>("safe"));
kernel
.Bind<IResolver>()
.To<UnsafeResolver>()
.Named("unsafe")
.BindingConfiguration.IsImplicit = true;
kernel
.Bind<IResolver>()
.To<SafeResolver>()
.Named("safe")
.BindingConfiguration.IsImplicit = true;
Here is how you would do the same thing with Pure DI:
var result = new SafeguardedResolver(new UnsafeResolver(), new SafeResolver());
The simplicity of Pure DI in cases like these is one of the reasons why IMO it is better than using a container.
Problem:
Assume the class:
public class MyAwesomeClass
{
private IDependCls _dependCls;
public MyAwesomeClass(IDependCls dependCls)
{
_dependCls = dependCls;
}
}
And somewhere else I need to get an instance of that class, like so:
public class SomewhereElse
{
public void AwesomeMethod()
{
//...
// AwesomeStuff
//...
var GetErDone = new MyAwesomeClass(); // PROBLEM! No constructor with 0 arguements
}
}
Question is, do I
Proposed solution 1:
A) have to make an extra constuctor that resolves the dependency? For example:
public MyAwesomeClass() // new constructor
{
_dependCls = DependencyResolver.Current.GetService<IDependCls>();
}
public class SomewhereElse
{
public void AwesomeMethod()
{
var GetErDone = new MyAwesomeClass(); // IT WORKS!!
}
}
Proposed solution 2:
B) use the resolver inside AwesomeMethod right before var GetErDone
public class SomewhereElse
{
public void AwesomeMethod()
{
var depCls = _dependCls = DependencyResolver.Current.GetService<IDependCls>();
var GetErDone = new MyAwesomeClass(depCls); // IT WORKS!!
}
}
Autofac solution?
C) Some other Autofac way?
Looking for best practices, as well as a good Autofac solution if possible. I think the first way is the worst as optional dependancies could lead to a lot of clutter.
Summary:
How do I get a new MyAwesomeClass() when MyAwesomeClass has dependencies?
Have a look at the Composition Root pattern.
You are right, pulling up the dependency resolution only moves the problem to another place. If you continue to move it upwards in your object graph, though, you will reach the entry point of your application. There you will compose your object graph.
Compare that to the Service Locator anti-pattern (using DependencyResolver in client classes in your case) and you will see that Composition Root is a superior solution.
First of all apart from constructor injection you can also use property injection and method injection. However constructor injection is most common and the fastest method so I suggest to stick to it.
The second thing you need to do is to register your MyAwesomeClassin the Autofac container along with its dependency, they have some nice examples right at their home page.
And the last thing - you should not create instances of MyAwesomeClass directly - use Autofac instead. Here is an updated example:
public void AwesomeMethod()
{
//...
// AwesomeStuff
//...
var GetErDone = DependencyResolver.Current.GetService<MyAwesomeClass>();
}
You can create a new instance of 'MyAwesomeClass' with reflection, resolving the constructor parameters with Autofac.
public static T Instance<T>() where T : class
{
Type instanceType = typeof(T);
ConstructorInfo constructorInfo = instanceType.GetConstructors()[0];
ParameterInfo[] constructorParamsInfo = constructorInfo.GetParameters();
object[] constructorParams = new object[constructorParamsInfo.Length];
for (int i = 0; i < constructorParamsInfo.Length; i++)
{
var parameterInfo = constructorParamsInfo[i];
var type = parameterInfo.ParameterType;
constructorParams[i] = Container.Resolve(type);
}
object instance = Activator.CreateInstance(instanceType, constructorParams);
return (T)instance;
}
If you want to resolve instance automatically via Autofac, you can only choose from this
Inject in constructor of your class
Inject in property, by using
var builder = new ContainerBuilder();
builder.RegisterType<Foo>().PropertiesAutowired();
Use global access by DependencyResolver.Current.GetService<IFoo>();
In the class containing MyAwesomeMethod take MyAwesomeClass as a constructor dependency. Autofac will take care of the instantiation.
I know that this question is old, but I found a quite useful link on the autofac documentation describing dynamic instantiation of classes.
Autofac Dynamic Instantiation
Perhaps it could be helpful for someone.
Can someone please explain the difference between SatisfyImportsOnce and ComposeParts and why one would work where the other doesn't?
Specifically I have a MVC Web application that I am using MEF in. Below is some code (from that application) that works when I use SatisfyImportsOnce but doesn't when I use ComposeParts. My understanding is that ComposeParts creates composable parts from an array of attributed objects and composes them in the specified composition container and that SatisfyImportsOnce composes the specified part by using the specified composition service. To my simple monkey brain even though the English is different they are semantically the same. Both use the CompositionContainer to spit exported types at import targets.
public class FormPartCustomatorFactory
{
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
private readonly List<Lazy<ICustomRenderer, ICustomRendererMetaData>> _rendererImports = new List<Lazy<ICustomRenderer, ICustomRendererMetaData>>();
private readonly Dictionary<string, Lazy<ICustomRenderer, ICustomRendererMetaData>> _renderers;
public static readonly FormPartCustomatorFactory Instance = new FormPartCustomatorFactory();
static CompositionContainer _container;
private FormPartCustomatorFactory()
{
using (var catalog = new DirectoryCatalog(HttpRuntime.BinDirectory, "*.dll"))
{
_container = new CompositionContainer(catalog);
_container.SatisfyImportsOnce(this); // <- Works
// _container.ComposeParts(this); // DOESN'T Work
_renderers = _rendererImports.ToDictionary(q => q.Metadata.Name, q => q);
}
}
~FormPartCustomatorFactory()
{
_container.Dispose();
}
public static ICustomRenderer Find(string name)
{
return Instance._renderers[name].Value;
}
}
SatisyImportsOnce will compose a type without registering it for recomposition. So, if you intend to use a type without support for recomposition, you can use SatisfyImportsOnce and it will do the work as usual, but any changes in the container (new parts added, or parts removed), then your instance won't automatically be recomposed to offer up these new parts.
In your instance, you are using:
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
...but through SatisfyImportsOnce, this import won't be recomposed.
If you are not worried about recomposition, you could change your code use constructor injection, so you could do:
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers.ToDictionary(r => r.Metadata.Name, r => r);
}
The reason I would suggest constructor injection, is that the set of Lazy<ICustomRenderer, ICustomRendererMetadata> instances are an explicit dependency your type requires, so it would be better to instantiate your type in a usable state, rather than instantiate and then require an additional step to get it ready for first time use.
This makes your FormPartCustomatorFactory type much more testable. To this end, if you were to change the constructor as such, then your method of making it a singleton wouldn't work. Instead, you could take advantage of the lifetime management functionality of MEF, so possibly redesign your type as:
public interface IFormPartCustomatorFactory
{
ICustomRenderer Find(string name);
}
[Export(typeof(IFormPartCustomerFactory)), PartCreationPolicy(CreationPolicy.Shared)]
public class FormPartCustomatorFactory : IFormPartCustomatorFactory
{
private IEnumerable<Lazy<ICustomRenderer, ICustomRendereMetadata>> _renderers;
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers;
}
public ICustomRenderer Find(string name)
{
return _renderers
.Where(r => r.Metadata.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
.Select(r => r.Value)
.FirstOrDefault();
}
}
Doing it this way means that your type is not dependent on MEF, it can be used without it, its more testable, and the CompositionContainer will manage the lifetime of the part, in this case the CreationPolicy.Shared (which is the default for exported types), uses a singleton lifetime strategy. You can then import an instance of IFormPartCustomator, you import the same singleton instance.
I would also argue that calling it a Factory is possibly wrong, as a factory is designed to create new instances, whereas, your type will only create one instance of each ICustomRenderer. If this is the intended behaviour, maybe it would be better called an FormPartCustomatorService, that implements an IFormPartCusomatorService interface? If you want to spin up new instances each time, you could look at ExportFactory<ICustomRenderer, ICustomRendererMetadata>.
As Matthew mentions, SatisfyImportsOnce doesn't register the part for recomposition. This means the MEF container doesn't hold a reference to the part.
In addition, SatisfyImportsOnce only satisfies the imports of a part, but ignores any exports it has. ComposeParts would add the exports to the container too.