Skip to main content
added 6229 characters in body
Source Link

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.

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.

edited title; edited tags; removed thanks
Source Link
t3chb0t
  • 44.3k
  • 9
  • 84
  • 190

Remove if else statement from code Mocking objects using abstract factory

Thanks in advance.

Remove if else statement from code

Thanks in advance.

Mocking objects using abstract factory

added 1466 characters in body
Source Link

I ended up withhave the following code on my Abstract factory class which I am not very happy with.

public class MockContext<T>
{
   public T CreateMockObject()
   {
      IFactory<T> factory = null;

     if (typeof(T).IsPrimitive || typeof(T) == typeof(string) || typeof(T) == typeof(decimal))
     {
        factory = new PrimitiveFactory<T>();
     }
     else if (typeof(T).IsArray)
     {
        factory = new ArrayFactory<T>();
     }
     else if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
     {
        factory = new CollectionFactory<T>();
     }
     else if (typeof(T).IsClass && typeof(T) != typeof(string))
     {
        factory = new ClassFactory<T>();
     }

      return factory.Create();
  }
 }
}

Which gets called by the following class

   public class Mocker
   {
      public T MockObject<T>()
      {
         MockContext<T> context = new MockContext<T>();
         T mockObject = context.CreateMockObject();

         return mockObject;
      }
   }

This abstract factory instantiates other factories depending on of the object.

Here is my class factory:

   public class ClassFactory<T> : IFactory<T>
   {
      public T Create()
      {
         T mockObject = (T)Activator.CreateInstance(typeof(T));
         IEnumerable<PropertyInfo> properties = typeof(T).GetProperties().Where(p => p.CanWrite);

         GenericMethodInvokerUtil method = new GenericMethodInvokerUtil();

         foreach (PropertyInfo property in properties)
         {
            if (property.PropertyType == typeof(T))
               throw new Exception("Circular properties are not supported!"); 

            method.InvokeMockObject<T>(property.PropertyType, property, mockObject);
         } 

         return mockObject;
      }
   }

I am using the above code as follows:

  static void Main(string[] args)
  {
     Mocker mocker = new Mocker();
     var mock = mocker.MockObject<Test>();
  }

With Test being some class with properties.

I ended up with the following code on my Abstract factory class which I am not very happy with.

  public T CreateMockObject()
  {
     IFactory<T> factory = null;

     if (typeof(T).IsPrimitive || typeof(T) == typeof(string) || typeof(T) == typeof(decimal))
     {
        factory = new PrimitiveFactory<T>();
     }
     else if (typeof(T).IsArray)
     {
        factory = new ArrayFactory<T>();
     }
     else if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
     {
        factory = new CollectionFactory<T>();
     }
     else if (typeof(T).IsClass && typeof(T) != typeof(string))
     {
        factory = new ClassFactory<T>();
     }

     return factory.Create();
  }

I have the following Abstract factory class which I am not very happy with.

public class MockContext<T>
{
   public T CreateMockObject()
   {
      IFactory<T> factory = null;

     if (typeof(T).IsPrimitive || typeof(T) == typeof(string) || typeof(T) == typeof(decimal))
     {
        factory = new PrimitiveFactory<T>();
     }
     else if (typeof(T).IsArray)
     {
        factory = new ArrayFactory<T>();
     }
     else if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
     {
        factory = new CollectionFactory<T>();
     }
     else if (typeof(T).IsClass && typeof(T) != typeof(string))
     {
        factory = new ClassFactory<T>();
     }

      return factory.Create();
  }
 }
}

Which gets called by the following class

   public class Mocker
   {
      public T MockObject<T>()
      {
         MockContext<T> context = new MockContext<T>();
         T mockObject = context.CreateMockObject();

         return mockObject;
      }
   }

This abstract factory instantiates other factories depending on of the object.

Here is my class factory:

   public class ClassFactory<T> : IFactory<T>
   {
      public T Create()
      {
         T mockObject = (T)Activator.CreateInstance(typeof(T));
         IEnumerable<PropertyInfo> properties = typeof(T).GetProperties().Where(p => p.CanWrite);

         GenericMethodInvokerUtil method = new GenericMethodInvokerUtil();

         foreach (PropertyInfo property in properties)
         {
            if (property.PropertyType == typeof(T))
               throw new Exception("Circular properties are not supported!"); 

            method.InvokeMockObject<T>(property.PropertyType, property, mockObject);
         } 

         return mockObject;
      }
   }

I am using the above code as follows:

  static void Main(string[] args)
  {
     Mocker mocker = new Mocker();
     var mock = mocker.MockObject<Test>();
  }

With Test being some class with properties.

Source Link
Loading