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?