Should I pass a Unity Container to my dependencies?

So, I have a:

Appendix A: Class B required (other assembly)

Class B: Class C required (again, another assembly)

Class C: a container is used to resolve various objects, but the lifetime of the container (and the objects allowed by it) must be controlled by the root of the composition.

I think I understand how this will work in most cases, but in class C I need to resolve based on the property of the passed object.

I think I am asking if the container has a dependency, and as such, what is the best way to get it where it is needed (not sure if I really would like to pass it through a bunch of constructors - will there be an embedding of the properties in the path?)

I believe this source is as clean and simple as I can get:

namespace InjectionTest { using System; using Microsoft.Practices.Unity; public class ApplicationA { static void Main(string[] args) { using (IUnityContainer container = new UnityContainer()) { // Normally I'd use this, but for clarity in the example, I'm doing it in code. //container.LoadConfiguration(); container.RegisterType<IClassB, ClassB>(); container.RegisterType<IClassC, ClassC>(); container.RegisterType<IFooBuilder, FrobBuilder>("frob"); container.RegisterType<IFooBuilder, WidgetBuilder>("widget"); IClassB machine = container.Resolve<IClassB>(); InitialObject bar = new InitialObject() { Name = "widget" }; machine.doSomethingWithBar(bar); bar = new InitialObject() { Name = "frob" }; machine.doSomethingWithBar(bar); } } } public class ClassB : IClassB { IClassC classC { get; private set; } public ClassB(IClassC classc) { this.classC = classc; } public void doSomethingWithBar(InitialObject bar) { var foo = this.classC.BuildMyFoo(bar); /* * Do something else with foo & bar * */ } } public interface IClassB { void doSomethingWithBar(InitialObject bar); } public class ClassC : IClassC { public ResultObject BuildMyFoo(InitialObject bar) { IFooBuilder builder = null; //How best do I get my container here? //IFooBuilder builder = container.Resolve<IFooBuilder>(bar.Name); return builder.build(bar); } } public interface IClassC { ResultObject BuildMyFoo(InitialObject bar); } public class InitialObject { public string Name { get; set; } } public class ResultObject { public string SomeOtherData { get; set; } } public interface IFooBuilder { ResultObject build(InitialObject bar); } public class FrobBuilder : IFooBuilder { public ResultObject build(InitialObject bar) { throw new NotImplementedException(); } } public class WidgetBuilder : IFooBuilder { public ResultObject build(InitialObject bar) { throw new NotImplementedException(); } } } 

Edit: so I did this with the introduction of the properties:

I changed ClassC:

 public class ClassC : IClassC { [Dependency] public IUnityContainer Container { get; set; } public ResultObject BuildMyFoo(InitialObject bar) { IFooBuilder builder = null; //How best do I get my container here? builder = Container.Resolve<IFooBuilder>(bar.Name); return builder.build(bar); } } 

and updated my main method in ApplicationA:

  public void Main() { using (IUnityContainer container = new UnityContainer()) { // Normally I'd use this, but for clarity in the example, I'm doing it in code. //container.LoadConfiguration(); container.RegisterType<IClassB, ClassB>(); container.RegisterType<IClassC, ClassC>(); container.RegisterType<IFooBuilder, FrobBuilder>("frob"); container.RegisterType<IFooBuilder, WidgetBuilder>("widget"); using (IUnityContainer child = container.CreateChildContainer()) { container.RegisterInstance<IUnityContainer>(child); IClassB machine = container.Resolve<IClassB>(); InitialObject bar = new InitialObject() { Name = "widget" }; machine.doSomethingWithBar(bar); bar = new InitialObject() { Name = "frob" }; machine.doSomethingWithBar(bar); } } } 
+4
source share
1 answer

You definitely do not want to go through containers. You should look into the support of the Unity factory, which will work in this situation. Something like that:

 container.RegisterType<IFooBuilder, FrobBuilder>("Frob") .RegisterType<IFooBuilder, WidgetBuilder>("Widget") .RegisterType<Func<string, IFooBuilder>>(new InjectionFactory(c => new Func<string, IFooBuilder>(barName => c.Resolve<IFooBuilder>(barName)))) 

and then ClassC will have a Func constructor parameter:

 public class ClassC : IClassC { private readonly Func<string, IFooBuilder> _builderFactory; public ClassC(Func<string, IFooBuilder> builderFactory) { _builderFactory = builderFactory; } public ResultObject BuildMyFoo(InitialObject bar) { IFooBuilder builder = _builderFactory(bar.Name); return builder.build(bar); } } 
+8
source

Source: https://habr.com/ru/post/1337164/


All Articles