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.
Related
I'd like to use an Autofac delegate factory to resolve an object graph where some of the nested objects need to be passed parameters. E.g. If the QuoteService in the Autofac delegate factory example required a url to retrieve data from, or the QuoteService itself had a dependency that required a parameter.
public class WebQuoteService : IQuoteService
{
public WebQuoteService(Uri source)
{
}
}
public class Shareholding
{
public Shareholding(string symbol, uint holding, IQuoteService quoteService)
{
}
}
I'd like to be able to declare and register a delegate like so:
public delegate Owned<Shareholding> ShareholdingFactory(string symbol, uint holding,
Uri source);
builder.RegisterGeneratedFactory<ShareholdingFactory>();
The problem I run into is that Autofac can't resolve the uri parameter of the WebQuoteService.
I've seen a few similar questions & solutions, but nothing particularly neat. Autofac-passing-parameter-to-nested-types suggests registering a lambda to explicitly implement the factory and resolve the nested dependency. I'm sure that would work, but it becomes very messy if the parameter is needed at a deeper level or when there are more dependencies.
The temporary solution I'm using is an improvement on that, resolving the IQuoteService in Shareholding OnPreparing, and forwarding the parameters created by the Autofac generated factory.
builder.RegisterType<Shareholding>().OnPreparing(e =>
{
e.Parameters = e.Parameters.Union(new[]
{
new TypedParameter(typeof (IQuoteService), e.Context.Resolve<IQuoteService>(e.Parameters))
});
});
That works ok and avoids manually resolving other parameters, but I actually need to do it twice to forward the parameters to a second nested level.
I've considered, but not tried to use BeginLifetimeScope(Action<ContainerBuilder>) as suggested by can-components-be-temporarily-registered-in-an-autofac-container. I think I'd have to implement the factory manually, but I could then register the uri so it would work at any nesting level.
What I'd actually like to be able to do is attach to WebQuoteService OnPreparing and access the delegate factory's parameters. Something like this can be made to work with reflection but that's obviously not ideal.
builder.RegisterType<WebQuoteService>().OnPreparing(e =>
{
var parameters = e.Context._context._activationStack.Last().Parameters;
e.Parameters = e.Parameters.Concat(parameters);
});
Can anyone suggest a cleaner alternative to pass parameters to objects nested two levels deep?
Sorry to self-answer, but failing a better suggestion I thought I should document the best solution I have.
In OnPreparing, you can use reflection to access the Autofac activation stack and the parameters passed to the delegate factory. These can then be added to the parameters of the nested component being resolved. This works with any level of nesting (it only needs to be added to OnPreparing for the component that requires parameters.)
Register like so:
builder.RegisterType<WebQuoteService>()
.OnPreparing(AutofacExtensions.ForwardFactoryParameters);
Using this helper class:
public static class AutofacExtensions
{
private static readonly FieldInfo ContextFieldInfo;
private static readonly FieldInfo ActivationStackFieldInfo;
static AutofacExtensions()
{
var autofacAssembly = typeof(IInstanceLookup).Assembly;
Type instanceLookupType = autofacAssembly.GetType("Autofac.Core.Resolving.InstanceLookup");
ContextFieldInfo = instanceLookupType.GetField("_context", BindingFlags.Instance | BindingFlags.NonPublic);
Type resolveOperationType = autofacAssembly.GetType("Autofac.Core.Resolving.ResolveOperation");
ActivationStackFieldInfo = resolveOperationType.GetField("_activationStack", BindingFlags.Instance | BindingFlags.NonPublic);
}
public static IResolveOperation Context(this IInstanceLookup instanceLookup)
{
return (IResolveOperation)ContextFieldInfo.GetValue(instanceLookup);
}
public static IEnumerable<IInstanceLookup> ActivationStack(this IResolveOperation resolveOperation)
{
return (IEnumerable<IInstanceLookup>)ActivationStackFieldInfo.GetValue(resolveOperation);
}
/// <summary>
/// Pass parameters from the top level resolve operation (typically a delegate factory call)
/// to a nested component activation.
/// </summary>
public static void ForwardFactoryParameters(PreparingEventArgs e)
{
var delegateFactoryActivation = ((IInstanceLookup) e.Context).Context().ActivationStack().Last();
e.Parameters = e.Parameters.Concat(delegateFactoryActivation.Parameters);
}
}
From version 6, Matt's answer no longer functions. Below is correct.
public static void ForwardFactoryParameters(PreparingEventArgs e)
{
var ctx = e.Context;
var oper = ctx.GetType().GetProperty("Operation").GetValue(ctx);
var requestStack = oper.GetType().GetProperty("InProgressRequests").GetValue(oper) as SegmentedStack<ResolveRequestContext>;
if (requestStack.Count == 1)
{
//Nothing to do; we are on the first level of the call stack.
return;
}
var entryRequest = requestStack.Last();
e.Parameters = entryRequest.Parameters;
}
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.
I have the following classes:
public interface IRenderer<T>
{
string Render(T obj);
}
public class Generic<T> { }
public class SampleGenericRenderer<T> : IRenderer<Generic<T>>
{
public string Render(Generic<T> obj)
{
throw new NotImplementedException();
}
}
I would like to be able to call StructureMap with
ObjectFactory.GetInstance<IRenderer<Generic<string>>>(); and receive SampleGenericRenderer<string>.
I'm currently using the following registration and receiving this error when I call GetInstance. "Unable to cast object of type:
ConsoleApplication1.SampleGenericRenderer'1[ConsoleApplication1.Generic'1[System.String]]'
to type
'ConsoleApplication1.IRenderer'1[ConsoleApplication1.Generic'1[System.String]].
public class CoreRegistry : Registry
{
public CoreRegistry()
{
Scan(assemblyScanner =>
{
assemblyScanner
.AssemblyContainingType(typeof(IRenderer<>));
assemblyScanner.AddAllTypesOf(typeof(IRenderer<>));
assemblyScanner
.ConnectImplementationsToTypesClosing(
typeof(IRenderer<>));
});
}
}
Is there any way to configure StructureMap so that it creates SampleGenericRenderer<string> instead of SampleGenericRenderer<Generic<string>>?
UPDATE: I ended up doing the type construction myself for this subset of dependencies. Because they combine contextual binding with a lot of unsupported generic bindings, this turned out to be the cleanest solution.
As Pete explained, there is probably no way with StructureMap to do this. Other DI containers might yield more success, but not all contains have great support for more complex generic trickery. The only one I know for sure that allows you to do this is the Simple Injector. With the Simple Injector, you just need the following configuration:
var container = new Container();
container.Register(typeof(IRenderer<>), typeof(SampleGenericRenderer<>));
// Usage
var renderer = container.GetInstance<IRenderer<Generic<string>>>();
renderer.Render(new Generic<string>());
More info about this method can be found here.
I don't believe StructureMap has any mechanism for closing an inner generic parameter like this.
It's not ideal, but you might try creating your own IRegistrationConvention and whenever encountering a type that is a closed type of Generic<>, do the following:
var generic_t = typeof(Generic<>).MakeGenericType(type);
var sample_renderer_t = typeof(SampleGenericRenderer<>).MakeGenericType(type);
var renderer_t = typeof(IRenderer<>).MakeGenericType(generic_t);
graph.AddType(renderer_t, sample_renderer_t);
See http://docs.structuremap.net/ScanningAssemblies.htm#section11 for more details.
For me this works:
class Program
{
static void Main()
{
ObjectFactory.Configure(x=>x.AddRegistry<CoreRegistry>());
var instance = ObjectFactory.GetInstance(typeof(IRenderer<string>)) as IRenderer<Generic<string>>;
var render = instance.Render(new Generic<string>());
}
}
This throws an exception:
ObjectFactory.GetInstance<IRenderer<Generic<string>>>();
What is your real problem?
EDIT:
Under some circumstances this could work too (If you don't know Generic<string> at design time):
static void Main()
{
ObjectFactory.Configure(x => x.AddRegistry<CoreRegistry>());
var instance = ObjectFactory.GetInstance(typeof(IRenderer<string>));
var methodInfo = instance.GetType().GetMethod("Render");
methodInfo.Invoke(instance, new[] { new Generic<string>() });
}
I asked a more general question a minute ago: How to organize DI Framework usage in an application?, and the feedback I got was that I was using a Service Locator Pattern rather than true DI as is pointed out by Martin Fowler here: http://martinfowler.com/articles/injection.html
Actually, I read that article just the other day, but apparently haven't quite grasped it.
So let's say I have the following code:
interface ICardReader
{
string GetInfo();
void SetDebugMode(bool value);
void Initialize(string accountToken);
void ShowAmount(string amount);
void Close();
ICreditCardInfo GetCardInfo();
}
public class MagTekIPAD: ICardReader
{
public ICreditCardInfo GetCardInfo()
{
var card = GetCardDataFromDevice();
// apparently the following line is wrong?
var ccInfo = Inject<ICreditCardInfo>.New();
ccInfo.Track1 = MakeHex(card.EncTrack1);
ccInfo.Track2 = MakeHex(card.EncTrack2);
ccInfo.MagSignature = MakeHex(card.EncMP);
ccInfo.MagSwipeKeySN = MakeHex(card.KSN);
ccInfo.MagSignatureStatus = MakeHex(card.MPSts);
ccInfo.MagDeviceSN = ipad.Serial;
ccInfo.MSREncryptType = "MAGENSA_V5";
return ccInfo;
}
// Other implementation details here ...
}
In this example I could inject the dependency into the constructor—and I think that's the correct way to fix 'this' scenario.
But what if I actually need to create an unknown number of the object in question (or are there any other legitimate reason I'd have a need to create the dependency on the fly in the class)?
This example gives me the impression that you try to create a data transfer object namingly ICreditCardInfo using an IoC container. Such objects should not have any real dependencies like a service. The proper way to create DTOs is to use the new operator:
return new CreditCardInfo(
MakeHex(card.EncTrack1),
MakeHex(card.EncTrack2),
MakeHex(card.EncMP),
MakeHex(card.KSN),
MakeHex(card.MPSts),
ipad.Serial,
"MAGENSA_V5");
Inject a factory for ICreditCardInfo objects into the constructor of MagTekIPAD
public class MagTekIPAD : ICardReader
{
private readonly Func<ICreditCardInfo> factory;
public MagTekIPAD(Func<ICreditCardInfo> factory)
{
this.factory = factory;
}
public ICreditCardInfo GetCardInfo()
{
var info = factory();
// ...
return info;
}
}
Several containers can auto-generate Func<T> delegates if they know how to create instances of T so you don't have to define factory interfaces or abstract factory classes.
As Fowler pointed out, Service Locator is the more direct approach and is less error prone.
Some Dependency Injection frameworks require you to declare whether you are dealing with Singleton or they can have different lifetimes.
I have a service layer that retrieves a DTO from a repository. Depending on a property in that DTO I need to use one of two strategies to perform calculations on the DTO. I have created a factory to return the appropriate strategy and I'm using a DI container (Munq) to instantiate the object.
public class CalculationFactory
{
private readonly IDependencyResolver _resolver;
public CalculationFactory(IDependencyResolver resolver)
{
ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
_resolver = resolver;
}
public static ICalculation CreateCalculator(int serviceType)
{
switch (serviceType)
{
case 1: return _resolver.Resolve<ICalculation>("Type1");
case 2: return _resolver.Resolve<ICalculation>("Type2");
default: return _resolver.Resolve<ICalculation>("InvalidType");
}
}
}
This requires me to pass in the dependency resolver when I instantiate the factory so that it can be used to resolve/instantiate the appropriate calculation to use. Is this the correct approach? If I want to add a new type of calculation then I would need to update the factory CreateCalculator method and register the new type.
Update (long)
I'm not really getting traction on the suggestions I'm afraid. I've gone back to my copy of Mark's DI in .Net and specifically chapter 6 on refactorings. So I have a class MeterReadings and I need to calculate a charge using one of two calculations based on a runtime value. I add an abstract factory to the mix but in my concrete factory I still need to new up the appropriate calculation. I feel like I'm missing the point here:
public enum ServiceType
{
Actuals = 1, CopyBlock,
}
public interface IChargeCalculator
{
decimal CalculateCharge();
}
public interface IChargeCalculatorFactory
{
IChargeCalculator CreateChargeCalculator(ServiceType serviceType);
}
public class MeterReading
{
private readonly IChargeCalculatorFactory chargeCalculatorFactory;
public MeterReading(IChargeCalculatorFactory chargeCalculatorFactory)
{
if (chargeCalculatorFactory == null)
throw new ArgumentNullException("chargeCalculatorFactory");
this.chargeCalculatorFactory = chargeCalculatorFactory;
}
}
public class ConcreteChargeCalculatorFactory : IChargeCalculatorFactory
{
public IChargeCalculator CreateChargeCalculator(ServiceType serviceType)
{
switch (serviceType)
{
case ServiceType.Actuals : return new ActualsChargeCalculator();
default: return new CopyBlockChargeCalculator();
}
}
}
But in my container I can register the different calculators and if I pass in the container as the concrete factory I get something like the following (not tested) which frankly looks fairly reasonable to me. Any feedback/clarification would be welcome.
Container.Register<IChargeCalculator>("Actuals",
c => new ActualsChargeCalculator());
Container.Register<IChargeCalculator>("CopyBlock",
c => new CopyBlockChargeCalculator());
...
public enum ServiceType
{
Actuals = 1, CopyBlock,
}
public interface IChargeCalculator
{
decimal CalculateCharge();
}
public class MeterReading
{
private readonly IDependencyResolver chargeCalculatorFactory;
private ServiceType serviceType;
public MeterReading(IDependencyResolver chargeCalculatorFactory)
{
if (chargeCalculatorFactory == null)
throw new ArgumentNullException("chargeCalculatorFactory");
this.chargeCalculatorFactory = chargeCalculatorFactory;
}
public decimal Charge
{
get
{
return chargeCalculatorFactory.Resolve<IChargeCalculator>(serviceType.ToString());
}
}
}
Yes, I would say you are doing it in a proper way.
Though you write that you need to "pass in the dependency resolver ", is there a reason that you can't have the factory class injected into the class where it is needed? Then the factorys dependency on the dependency resolver should be resolved by the dependency resolver itself (to itself).
I hope that sentence made sense.
I have tried to come up with a "cleaner" solution, but have not found any yet. A solution similar to what is suggested in the question (which is not exactly the same) Dessus links is certainly possible, but I really see that as just moving the same code to another place. Remo also writes that it could be done in a factory class instead of a factory method.
It's a bit like deciding between writing a lampda or a helper class. It mostly comes down to readabilty, and for me a factory method is just to big, and having it in a module initializer or bootstrapper seams to disorganized.
BTW I can recommend Ninject, it is a really good, clean DI. Plus it's documentation uses Ninja examples ;)
I believe this question has been answered here, where it is suggested you use meta data against your bindings and create bindings for each implementation. You then use a binding to pull the meta data to choose which binding to use: Ninject conditional binding based on property value . Possibly this may or may not be possible with Munq? Not sure.
The person (Remo) who answered that question is one of the architects of ninject, and is very knowledgeable. I believe that his answer should hold alot of weight. (I am a basing this of being a subscriber to the ninject mailing list, and seeing him answer about half of all the questions).