Here's an example of a static generic Class that will return instances of new Classes where the internal data type used by the new Class is constrained to be a struct. I believe this example demonstrates the "usual" features of implementing the Factory Class pattern in C#: use of an interface; generic constraints, etc.
using System;
namespace StructClassFactoryDemo
{
internal interface IGenericStruct<T> where T : struct
{
T[] Parameters { set; get; }
void Execute(Func<T,T> paramFunc, T[] parameters);
}
internal static class GenericStructFactory<T> where T : struct
{
internal static GenericStructClass<T> Create(Func<T,T> paramFunc, params T[] parameters)
{
GenericStructClass<T> newT = new GenericStructClass<T>();
if (paramFunc != null) newT.Execute(paramFunc, parameters);
Console.WriteLine("created {0} type", typeof(T).Name);
return newT;
}
}
public class GenericStructClass<T> : IGenericStruct<T> where T : struct
{
public T[] Parameters { set; get; }
public void Execute(Func<T,T> paramFunc, T[] parameters)
{
if (parameters == null) return;
if (typeof(T).IsValueType && paramFunc != null)
{
for (int i = 0; i < parameters.Length; i++)
{
parameters[i] = paramFunc(parameters[i]);
}
}
Parameters = parameters;
}
}
}
Here's how you might use this Factory in some Class:
Func<int,int> intFunc = (x) =>
{
return x + 100;
};
Func<double, double> doubleFunc = (x) =>
{
return x + 43.024;
};
GenericStructClass<int> ClassA0 = GenericStructFactory<int>
.Create(
null,
new int[] { 1, 2, 3, 4, 5, 6 });
GenericStructClass<int> ClassA1 = GenericStructFactory<int>
.Create(
intFunc,
new int[] { 1, 2, 3, 4, 5, 6 });
GenericStructClass<double> ClassA2 = GenericStructFactory<double>
.Create(
doubleFunc,
new double[] { 1.24, 2.23, 3.5, 4.9, 5.1, 6.2 });
GenericStructClass<long> ClassA3 = GenericStructFactory<long>
.Create(
x => x + 23,
new long[] { 1, 2, 3, 4, 5, 6 });
GenericStructClass<DateTime> ClassA4 = GenericStructFactory<DateTime>
.Create(
dt => dt.AddDays(100),
new DateTime[]
{
DateTime.Now, DateTime.Now.AddDays(1), DateTime.Now.AddDays(2)
});
Notes:
1. even though an Interface is implemented here, the code shown really does not demonstrate its use in a
specific way; so, why's it there ? : imho, it is often the case that you
will want to extend a Factory class, and you would use the Interface shown to define another Class that would be used as an alternative to 'GenericStructClass. Further, imho, it is a good idea to use Interfaces to "enforce discipline" in development.
2. Note that you can't use 'ValueType as a constraint in a Generic Class, but you can use 'Struct, and, within a Generic Class, you can test to see if the Generic Type is a 'ValueType, as shown here.