Here is my Primitive factory:
public class PrimitiveFactory<T> : IFactory<T>
{
private readonly Dictionary<Type, IPrimitiveFactory<T>> _primitiveFactories = new Dictionary<Type, IPrimitiveFactory<T>>()
{
{ typeof(string), new StringFactory() as IPrimitiveFactory<T> },
{ typeof(bool), new BooleanFactory() as IPrimitiveFactory<T> },
{ typeof(byte), new ByteFactory() as IPrimitiveFactory<T> },
{ typeof(sbyte), new SbyteFactory() as IPrimitiveFactory<T> },
{ typeof(char), new CharFactory() as IPrimitiveFactory<T> },
{ typeof(decimal), new DecimalFactory() as IPrimitiveFactory<T> },
{ typeof(double), new DoubleFactory() as IPrimitiveFactory<T> },
{ typeof(float), new FloatFactory() as IPrimitiveFactory<T> },
{ typeof(int), new IntFactory() as IPrimitiveFactory<T> },
{ typeof(uint), new UintFactory() as IPrimitiveFactory<T> },
{ typeof(long), new LongFactory() as IPrimitiveFactory<T> },
{ typeof(ulong), new UlongFactory() as IPrimitiveFactory<T> },
{ typeof(short), new ShortFactory() as IPrimitiveFactory<T> },
{ typeof(ushort), new UshortFactory() as IPrimitiveFactory<T> },
{ typeof(object), new ObjectFactory() as IPrimitiveFactory<T> },
};
public T Create()
{
if (_primitiveFactories.ContainsKey(typeof(T)))
{
IPrimitiveFactory<T> primitiveFactory = _primitiveFactories[typeof(T)];
return primitiveFactory.Create();
}
throw new KeyNotFoundException($"The key of type: {typeof(T)} is not found.");
}
}
All primitive types has their own factories which is determined by the type of the object.
Array factory:
public class ArrayFactory<T> : IFactory<T>
{
public T Create()
{
var genericMethodInvoker = new GenericMethodInvokerUtil();
Array array = Activator.CreateInstance(typeof(T), new object[] { RandomUtil.Instance.Next(1, 100) }) as Array;
for (int i = 0; i < array.Length; i++)
{
Type arrayElementType = typeof(T).GetElementType();
array.SetValue(genericMethodInvoker.InvokeMockObject<T>(arrayElementType), i);
}
return (T)Convert.ChangeType(array, typeof(T));
}
}
Collection factory
public class CollectionFactory<T> : IFactory<T>
{
public T Create()
{
ICollectionFactory<T> factory = null;
if (typeof(IDictionary).IsAssignableFrom(typeof(T)))
{
factory = new DictionaryFactory<T>() as ICollectionFactory<T>;
}
else if (typeof(IList).IsAssignableFrom(typeof(T)))
{
factory = new ListFactory<T>() as ICollectionFactory<T>;
}
return factory.Create();
}
}
Collections are on the other hand are separated in tow Dictionary and List
public class DictionaryFactory<T> : ICollectionFactory<T>
{
public T Create()
{
GenericMethodInvokerUtil methodInvoker = new GenericMethodInvokerUtil();
IDictionary dictionary = (IDictionary)Activator.CreateInstance(typeof(T));
int numberOfElements = RandomUtil.Instance.Next(1, 100);
Type[] arguments = dictionary.GetType().GetGenericArguments();
Type keyType = arguments[0];
Type valueType = arguments[1];
for (int i = 0; i < numberOfElements; i++)
{
object key = methodInvoker.InvokeMockObject<object>(keyType);
object value = methodInvoker.InvokeMockObject<object>(valueType);
if (!dictionary.Contains(key))
{
dictionary.Add(key, value);
}
}
return (T)dictionary;
}
}
And List factory
public class ListFactory<T> : ICollectionFactory<T>
{
public T Create()
{
GenericMethodInvokerUtil methodInvoker = new GenericMethodInvokerUtil();
IList list = (IList)Activator.CreateInstance(typeof(T));
int numberOfElements = RandomUtil.Instance.Next(1, 100);
Type valueType = list.GetType().GetGenericArguments()[0];
for (int i = 0; i < numberOfElements; i++)
{
object value = methodInvoker.InvokeMockObject<object>(valueType);
list.Add(value);
}
return (T)list;
}
}
Mock object gets called recursively from the following utility class:
public class GenericMethodInvokerUtil
{
public object InvokeMockObject<T>(Type type, PropertyInfo property, object currentObject)
{
object concreteResult = GetMockObjectResult(type);
property.SetValue(currentObject, concreteResult);
return currentObject;
}
public object InvokeMockObject<T>(Type type)
{
object concreteResult = GetMockObjectResult(type);
return concreteResult;
}
private object GetMockObjectResult(Type type)
{
MethodInfo method = typeof(Mocker).GetMethod("MockObject", new Type[0] { });
MethodInfo generic = method.MakeGenericMethod(type);
object instance = Activator.CreateInstance(typeof(Mocker));
object result = generic.Invoke(instance, null);
object concreteResult = Convert.ChangeType(result, type);
return concreteResult;
}
}
You can find the complete source of the project in my github HERE.