How to implement constructor injection in factory?

When you use the factory pattern, how do you add dependencies to constructors at runtime?

I create Foos with various formats - boolean, array, freetext, matrix, etc. This format will grow as we find various uses for Foo. Here is my main primary domain:

public interface IFoo { FooFormat Format { get; } } public class Foo : IFoo { private FooFormat _format; internal Foo(FooFormat format) { _format = format; } public FooFormat Format { get { return _format; } } } public abstract class FooFormat { } public class DefaultFooFormat : FooFormat { } public class BooleanFooFormat : FooFormat { public IList<bool> Values { get; set; } } public class ArrayFooFormat : FooFormat { private IList<string> _values; public ArrayFooFormat(IList<string> values) { _values = values; } public IList<string> Values { get { return _values; } } } 

IFoo is issued for the consumer context:

 public abstract class FooDecorator : IFoo { private IFoo _foo; protected FooDecorator(IFoo foo) { _foo = foo; } public FooFormat Format { get { return _foo.Format; } } protected IFoo foo { get { return _foo; } } } 

I don't want my consumer to instantly create Foo, so I force them to use factory:

 public abstract class FooFactory { protected IFoo Build<T>() { FooFormat format = GetFormat<T>(); return new Foo(format); } private FooFormat GetFormat<T>() { if (typeof(T) == typeof(ArrayFooFormat)) return new ArrayFooFormat(new List<string>()); if (typeof(T) == typeof(BooleanFooFormat)) return new BooleanFooFormat(); return new DefaultFooFormat(); } } 

And even then, they should get a factory from my abstract factory for their specific context.

I specifically create foos in the html context, for example:

 public class HtmlFoo : FooDecorator { public HtmlFoo(IFoo foo) : base(foo) { } public string ToHtml() { return "<div>" + this.Format.ToString() + "</div>"; } } public class HtmlFooFactory : FooFactory { public IFoo BuildFoo<T>() { IFoo foo = Build<T>(); return new HtmlFoo(foo); } } public class HtmlFooConsumer { public void DoSomeFoo() { var factory = new HtmlFooFactory(); var htmlBooleanFoo = factory.BuildFoo<BooleanFooFormat>(); var htmlArrayFoo = factory.BuildFoo<ArrayFooFormat>(); } } 

My problem is in my abstract FooFactory: I always insert an empty list of values ​​into my ArrayFooFormat. I want to be able to pass in a list of values ​​from the consumer. For other FooFormats, I want to pass the correct constructor arguments from the consumer. But I want the public API to be simple - I don't want a bunch of overloads on BuildFoo ().

So, how do I pass a list of custom values ​​to a factory.BuildFoo <T> () call from inside HtmlFooConsumer.DoSomeFoo ()? Any ideas, stackoverflow gurus?

+4
source share
2 answers

Perhaps you can do something on these lines where your abstract FooFormat becomes IFooFormat and the generic FooFormat provides an Init method that takes this parameter.

Then one Build overload allows you to pass a parameter.

 public interface IFooFormat { } public class FooFormat<TValue> : IFooFormat { private TValue _value; public void Init(TValue value) { _value = value; } public TValue Value { get { return _value; } } } public class ArrayFooFormat : FooFormat<IList<string>> { } public class BooleanFooFormat : FooFormat<bool> { } public class DefaultFooFormat : IFooFormat { } public interface IFoo { } public class Foo : IFoo { private IFooFormat _format; internal Foo(IFooFormat format) { _format = format; } public IFooFormat Format { get { return _format; } } } public class FooFactory { protected IFoo Build<TFormat, TArg>(TArg arg) where TFormat : FooFormat<TArg>, new() { TFormat format = new TFormat(); format.Init(arg); return new Foo(format); } protected IFoo Build<TFormat>() where TFormat : IFooFormat, new() { return new Foo(new TFormat()); } } 
+2
source

A factory is basically an object-oriented version of a static variable. I would avoid using one of them. Instead of forcing clients to use a factory, perhaps you can just insert objects into your constructors, bypassing the need for a factory.

0
source

All Articles