How do you implement constructor injection in a factory? - c#

When you're using a factory pattern, how do you inject dependencies into constructors at runtime?
I'm building Foos with different formats - boolean, array, freetext, matrix, etc. That format list will grow as we find different uses for Foo. Here's my basic core 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 decorated 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 instantiate a Foo directly, so I force them to use a 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 need to derive a factory from my abstract factory for their particular context.
I'm specifically building foos in an html context, like so:
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'm always injecting an empty value list into my ArrayFooFormat. I want to be able to pass in a value list from the consumer. For other FooFormats, I want to pass in the right constructor arguments from the consumer. But I want to keep the public API dead simple - I don't want a bunch of overloads on BuildFoo().
So how do I pass a custom value list into the factory.BuildFoo<T>() call from inside HtmlFooConsumer.DoSomeFoo()? Any ideas, stackoverflow gurus?

Maybe you can do something along these lines where your abstract FooFormat becomes IFooFormat and a generic FooFormat provides an Init method that gets passed the parameter.
Then a single overload of Build lets you pass in the 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());
}
}

A factory is basically the object oriented version of a static variable. I'd avoid using one alltogether. Instead of forcing clients to use a factory, perhaps you can simply inject objects into their constructors, sidestepping the need for a factory.

Related

C# Moq: Cannot convert Moq.Mock<Arbiter> to Arbiter

I have an interface Arbiter
public interface Arbiter
{
ContextData GetContextData();
}
I have a class that implements this interface.
public class ContextArbiter : Arbiter
{
ContextData m_data;
public CMBusContextArbiter()
:
base()
{
m_data = new ContextData();
}
public ContextData GetContextData()
{
return m_data;
}
}
I have another class that uses this interface
public class SelectData
{
private Arbiter m_Arbiter;
public SelectData(Arbiter Arbiter)
{
m_Arbiter = Arbiter;
}
public string RetrieveId()
{
return m_Arbiter.GetContextData().RouteId;
}
}
Now I want to unit test this class
public class SelectDataTest : UnitTestBase
{
private Mock<Arbiter> Arbiter;
private SelectData SelectData;
[OneTimeSetUp]
public void OneTimeSetup()
{
Arbiter= new Mock<Arbiter>();
SelectData = new SelectData(Arbiter);
}
}
But it seems that I can't pass the mock object to the SelectData class. It shows
Cannot convert Moq.Mock to Arbiter.
How can I get around this issue.
Use the Object property of the Mock<T> class to access the mocked object.
//...
Arbiter = new Mock<Arbiter>();
SelectData = new SelectData(Arbiter.Object);
//...
Reference Moq Quickstart

How to return interface using generic in C#

I am new in C# Generic concept and I would like to return interface implemented class using generic concept. Below is my example which is currently implemented without generic:
1) Factory Class which return interface and this class has two overload method which accept different data model:
public class Factory
{
public ICommon Init(DBInfoData dbInfoData)
{
return new ClassA(dbInfoData);
}
public ICommon Init(WebInfoData webInfoData)
{
return new ClassB(webInfoData);
}
}
2) Interface and interface implemented two class as below:
//=== Common Interface
public interface ICommon
{
void MethodA();
void MethodB();
}
//=== Internal access only ClassA
internal class ClassA : ICommon
{
private DBInfoData _DBInfoData = null;
public ClassA(DBInfoData dbInfoData)
{
_DBInfoData = dbInfoData;
}
public void MethodA()
{
throw new NotImplementedException();
}
public void MethodB()
{
throw new NotImplementedException();
}
}
//=== Internal access only ClassB
internal class ClassB : ICommon
{
private WebInfoData _WebInfoData = null;
public ClassB(WebInfoData webInfoData)
{
_WebInfoData = webInfoData;
}
public void MethodA()
{
throw new NotImplementedException();
}
public void MethodB()
{
throw new NotImplementedException();
}
}
3) Data Model class as below:
//=== Database Information
public class DBInfoData
{
public string Server { get; set; }
public string Database { get; set; }
}
//=== Web Server Information
public class WebInfoData
{
public string URL { get; set; }
public int Port { get; set; }
}
Now I want to implement generic functionality of C# where in factory class I do not want to declare two overload method. Using single method I can return ClassA or ClassB based on Data Model pass.
You could edit the Init method without having to edit anything else. This method will take a generic type parameter T, which can be of any type. Then you can use the is operator, which according to the docs used to type testing. You need to check however for any unsupported type of T, because you didn't add any constraint to the generic type passed. A raw implementation would be:
public class Factory
{
public ICommon Init<T>(T infoData)
{
if (infoData is DBInfoData dbInfoData) {
return new ClassA(dbInfoData);
}
if (infoData is WebInfoData webInfoData) {
return new ClassB(webInfoData);
}
throw new Exception($"Cannot create instance for info data of type {infoData.GetType().Name}");
}
}
And to test it:
var factory = new Factory();
var t1 = factory.Init(new DBInfoData()); // will be ClassA
var t2 = factory.Init(new WebInfoData()); // ClassB
To sophisticate it, you could introduce type constraint on your generic T class to make sure you can only pass appropriate types. For the current situation, you could create a marker interface for your classes DBInfoData and WebInfoData by introducing an empty interface say IInfoData. Then you have to inherit your classes like this:
public interface IInfoData {}
public class DBInfoData : IInfoData
{
public string Server { get; set; }
public string Database { get; set; }
}
public class WebInfoData : IInfoData
{
public string URL { get; set; }
public int Port { get; set; }
}
Now both inherits from (actually 'marked by') your base interface. Introduce a constraint to your factory to allow only descendants of IInfoData to be passed as an argument (so either DBInfoData or WebInfoData) by adding a constraint shown in the docs I linked above:
public class Factory
{
public ICommon Init<T>(T infoData) where T: IInfoData
{
if (infoData is DBInfoData dbInfoData) {
return new ClassA(dbInfoData);
}
if (infoData is WebInfoData webInfoData) {
return new ClassB(webInfoData);
}
throw new Exception($"Cannot create instance for info data of type {infoData.GetType().Name}");
}
}
Any type other than the descendants of IInfoData will cause a compilation error, and you're done. Use it like in my previous example:
var factory = new Factory();
var t1 = factory.Init(new DBInfoData()); // will be ClassA
var t2 = factory.Init(new WebInfoData()); // ClassB

How should I choose an instance of an AbstractFactory?

Currently I'm having a trouble with instantiating an AbstractFactory. There are some classes:
abstract class ABase { }
class A1 : ABase { }
class A2 : ABase { }
abstract class BBase { }
class B1 : BBase
{
private readonly A1 _a;
public B1(A1 a)
{
_a = a;
}
}
class B2 : BBase
{
private readonly A2 _a;
public B2(A2 a)
{
_a = a;
}
}
abstract class FactoryBBase
{
abstract public BBase Create(ABase b);
}
class FactoryB1 : FactoryBBase
{
override public BBase Create(ABase b)
{
return new B1(b as A1);
}
}
class FactoryB2 : FactoryBBase
{
override public BBase Create(ABase b)
{
return new B2(b as A2);
}
}
class Runtime
{
public void ProcessA(ABase a)
{
//How should I choose a proper factory?
}
}
How do I instantiate a proper abstract factory in ProcessA method depending on the type of a? The thing is that I don't want to have a big if/else block.
how to instantiate a proper abstract factory in ProcessA method depending on the type of a?
To avoid big if/else block you can put all factories into a map, where key is the type of a and value is the implementation. in Java I would do this either by Spring or I would create a static code, that can initialize the map when the class is loaded.
do I use AbstractFactory pattern as it is supposed to be uesd?
IMHO yes.
You can use a lookup dictionary instead of a if-else/switch construct.
//classes used as markers
public interface IMarker {}
public class MarkerA : IMarker {}
public class MarkerB : IMarker {}
//classes to be created
public interface IData {}
public class DataA : IData {}
public class DataB : IData {}
//factory to call abstract factories (could use static here)
public class Factory
{
public IData Create(IMarker marker)
{
//lookup dictionary instead of if/switch
//func ensures instance is only created when required
var lookup = new Dictionary<Type, Func<DataFactoryBase>>()
{
{ typeof(MarkerA), () => new DataAFactory() },
{ typeof(MarkerB), () => new DataBFactory() },
};
//get factory by type and call constructor
return lookup[marker.GetType()]().Create();
}
}
//abstract factories
public abstract class DataFactoryBase
{
public abstract IData Create();
}
public class DataAFactory : DataFactoryBase
{
public override IData Create()
{
return new DataA();
}
}
public class DataBFactory : DataFactoryBase
{
public override IData Create()
{
return new DataB();
}
}
public static void Main()
{
//example will return DataA
IData data = new Factory().Create(new MarkerA());
}
How to implement abstract factory really depends on what you need. What you have there is indeed a proper implementation, but I think it's not exactly what you need since you want to do something differently dependending on the type or state of an instance of ABase.
The logic that analyses the type or state is exactly what I'd put into a factory.
abstract class ABase { }
class A1 : ABase { }
class A2 : ABase { }
public abstract class FactoryBBase
{
public abstract IProcessor Create(ABase a);
}
public class ConcreteFactory : FactoryBBase
{
override public IProcessor Create(ABase a)
{
// this is ugly for a large amount of ABase implementations of course
if (a is A1)
{
return new Runtime1();
}
if (a is A2)
{
return new Runtime2();
}
throw new NotSupportedException();
}
}
public interface IProcessor
{
void ProcessA(ABase a);
}
public class Runtime1 : IProcessor
{
public void ProcessA(ABase a)
{
// process away
}
}
public class Runtime2 : IProcessor
{
public void ProcessA(ABase a)
{
// process away differently
}
}
Multiple factory implementations come into play when you want the same type of ABase implementation to be processed by different types of Runtime/Processor depending on state that is outside of ABase.

How to return child types from a static generic property

I want to have a base class:
public class Base
{
public static T Instance
{
get
{
// do something to return new instance of inherit class from itself
}
}
}
Class1:
public class Class1 : Base
{
// method and properties here
public string Func1()
{
return 'class1';
}
}
Class2:
public class Class2 : Base
{
// method and properties here
public string Func1()
{
return 'class2';
}
}
I want it so that we can use Class1 or Class2 like this
public class Main
{
var a = Base<Class1>.Instance.Func1(); // return 'class1'
var b = Base<Class2>.Instance.Func1(); // return 'class2'
}
Please help me to do this.
This is not called dynamic but polymorphic. In this case achieved with generics. Your only remaining problem is calling the constructor, which becomes possible when you put a Type-constraint on <T>.
public class Base<T> where T : new()
{
public static T Instance
{
get
{
// do something to return new instance of inherit class from itself
return new T();
}
}
}
and then:
public class Class1 : Base<Class1> { ... }
public class Class2 : Base<Class2> { ... }
But note that a simpler solution could be achieved with virtual+override methods or with an interface.
Alternative suggestion with some tighter type constraints:
namespace My.Test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Base<Class1>.Instance.Func1());
Console.WriteLine(Base<Class2>.Instance.Func1());
}
}
public abstract class Base
{
public abstract string Func1();
}
public sealed class Base<T> where T : Base, new()
{
public static T Instance
{
get { return new T(); }
}
}
public class Class1 : Base
{
public override string Func1() { return "class 1"; }
}
public class Class2 : Base
{
public override string Func1() { return "class 2"; }
}
}

Keep a Dictionary<Type, MyClass<T>> where elements are referenceable by type

I have an abstract class called EntityTypeTransform with a single abstract method designed to hold a Func delegate that converts an IDataRecord into an instance of T.
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
An implementation of that class might look like (does look like) this:
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
Now I want to keep an instance of each of these classes in a generic Dictionary, something like:
Dictionary<Type, EntityTypeTransform<T>>
But this doesn't work because (for example) an instance of EntityTypeTransform Of Task is not the same as an instance of EntityTypeTransform Of TaskParameter.
Can anyone help me out?
Edit: I should add that the Type key = typeof(T)
Actually, you don't need to use a dictionary at all! You can use the fact that GenericClass<T> is actually a different type for each T, so it can have its own static fields (i.e. GenericClass<Foo>.SomeField is not shared with GenericClass<Bar>.SomeField)
For instance you can implement your cache like this:
static class TransformCache<TEntityType>
{
public static EntityTypeTransform<TEntityType> Transform { get; set; }
}
And use it like this:
TransformCache<TaskParameter>.Transform = new TaskParameterEntityTypeTransform();
You can't specify a strong-typed collection that would hold different generic types. Here's the approach I've used in a similar problem, modified to match your requirement:
class TransformCollection
{
private Hashtable cache = new Hashtable();
public void Add<T>(EntityTypeTransform<T> transform) where T : class
{
this.cache[typeof(T)] = itemToCache;
}
public bool Exists<T>() where T : class
{
return this.cache.ContainsKey(typeof(T));
}
public EntityTypeTransform<T> Get<T>() where T : class
{
if (!this.Exists<T>())
throw new ArgumentException("No cached transform of type: " + typeof(T).Name);
return this.cache[typeof(T)] as EntityTypeTransform<T>;
}
}
This gives you type-safe cache for your generic type (though type-safety is enforced by the class's logic, not C#). You can use it as follows:
var collection = new TransformCollection();
collection.Add(SomeMethodToGetTransform<Task>());
//...
if (collection.Exists<Task>())
{
var transform = collection.Get<Task>();
//...
}
You could use an interface that is non-generic and then implement that interface explicitly inside that abstract class, It's pretty common in the .Net library itself:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform
where TEntityType : class
{
public virtual Func<IDataRecord, TEntityType> GetDataTransform()
{
return this.GetDataTransformImpl();
}
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
Func<IDataRecord, object> IEntityTypeTransform.GetDataTransform()
{
return this.GetDataTransform();
}
}
You would have to create a non-generic base class, e.g.
public abstract class EntityTypeTransformBase
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : EntityTypeTransformBase where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
public override Func<IDataRecord, object> GetDataTransform()
{
return GetDataTransformImpl();
}
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransformImpl()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
Now you can create your dictionary:
var d = new Dictionary<Type, EntityTypeTransformBase>();
d.Add(typeof(TaskParameter), new TaskParameterEntityTypeTransform());
You can use KeyedByTypeCollection to get type-safety and you can define an interface with a covariant type parameter to make sure that only objects of type EntityTypeTransform<T> can be added to the dictionary:
public interface IEntityTypeTransform<out TEntityType> where TEntityType : class
{
TEntityType Transform(IDataRecord dataRecord);
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract TEntityType Transform(IDataRecord dataRecord);
}
public class TaskParameter
{
public int TaskId;
public string Name;
public string Value;
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override TaskParameter Transform(IDataRecord dataRecord)
{
return new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
public class SomeClass
{
public KeyedByTypeCollection<IEntityTypeTransform<object>> TransformDictionary = new KeyedByTypeCollection<IEntityTypeTransform<object>>()
{
new TaskParameterEntityTypeTransform(),
// More transforms here
};
}
Now you can use it like this:
public void SomeMethod(IDataRecord dataRecord)
{
TaskParameter taskParameter = TransformDictionary.Find<TaskParameterEntityTypeTransform>().Transform(dataRecord);
}
I have tried to understand what you exactly want I hope this is exactly what you are looking for!
You shall set in TaskParameter class the correct parameters: TaskId, Name, Value
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return x => new TaskParameter { X = x.FieldCount };
}
}
public class TaskParameter
{
public int X { get; set; }
}
Dictionary<Type, EntityTypeTransform<TaskParameter>> imADict;
Add a non generic interface to your transformers:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<T> : IEntityTypeTransform
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, object> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task id"],
};
}
}
Then you can encapsulate your dictionary for ensure that datatypes will always match. Never allow to add a IEntityTypeTransform of a bad type :
public class TransformDistributor
{
private readonly Dictionary<Type, IEntityTypeTransform> _transforms = new Dictionary<Type, IEntityTypeTransform>();
public void Add<T>(EntityTypeTransform<T> type)
{
this._transforms.Add(typeof(T), type);
}
public T Transform<T>(IDataRecord record)
{
var transform = this._transforms[typeof(T)].GetDataTransform()(record);
if (transform is T)
{
return (T)transform;
}
else
{
// theorically can't happen
throw new InvalidOperationException("transformer doesn't return instance of type " + transform.GetType().Name);
}
}
}
The advantage are that at compile time, your are sure that nobody can insert a bad transformer, even if your are not using generics.
Usage :
var transforms = new TransformDistributor();
transforms.Add<TaskParameter>(new TaskParameterEntityTypeTransform());
var taskParameter = transforms.Transform<TaskParameter>(new DataRecord());

Categories