How to create Factory for Generic Class - c#

I have next interface
public interface IProperty<T>
{
T Data { get; set; }
}
public abstract class SomeAbsProperty<T> : IProperty<T> where T : class
{
protected SomeAbsProperty(int param1) {}
public abstract T GetData();
public I Data { get; set; }
}
And I have list of childres classes that based on SomeAbsProperty class
they looks like (simple example)
public sealed class ChildrenProperties : SomeAbsProperty<SomeClasss>
{
public ChildrenProperties(int param1):base(param1) {}
public override object GetData()
{
return new SomeClasss()
}
}
I would like to have some factory that would build specific class based on some type
public static class MyFactory
{
public static SomeAbsProperty<T> CreateObject<T>(PropertyName property) where T : class
{
switch (property)
{
case PropertyName.p1:
return new ChildrenProperties1(siteSettings, packageDateContext);
case PropertyName.p2:
return new ChildrenProperties(siteSettings, packageDateContext);
case PropertyName.p3:
return new ChildrenProperties2(siteSettings, packageDateContext);
case PropertyName.p4:
return new ChildrenProperties3(siteSettings, packageDateContext);
default:
return null;
}
}
}
but compelator can't convert my clases to SomeAbsProperty
what would be correct behavior here ?

You can use as casting to SomeAbsProperty<T> generic class, something like
return new ChildrenProperties(10) as SomeAbsProperty<T>;
Of-course you must be sure that ChildrenProperties is indeed SomeAbsProperty (which you know it is if you wrote base classes and factory class). You can not use explicit compile time casting.
Edit:
Maybe its better if factory which creates instances only depends on generic parameter (this will work only if all specializations have different parameter T; I'm not sure if that is your situation). Something like:
public static SomeAbsProperty<T> CreateObject<T>() where T : class
{
Type type = typeof(T);
if (type == typeof(object))
{
return new ChildrenProperties() as SomeAbsProperty<T>;
}
else if (type == typeof(string))
{
return new ChildrenPropertiesString() as SomeAbsProperty<T>;
}
else
{
return null;
}
}
... then you can call factory with something like:
SomeAbsProperty<object> h = MyFactory.CreateObject<object>();
Console.WriteLine(h.GetType().ToString());
SomeAbsProperty<string> h2 = MyFactory.CreateObject<string>();
Console.WriteLine(h2.GetType().ToString());

Related

C# Reflection dynamically create concrete class instance of T

I want to do something at runtime with objects based on there type.
Depending on the type I need to do different operations so I thought I would create
an abstract class like this:
internal abstract class DataOperator<T>
where T : class
{
public abstract void DoSomething(IList<T> data);
}
with multiple concrete implementations like:
class MyClassOperator : DataOperator<MyClass>
{
public override void DoSomething(IList<MyClass> data)
{
throw new NotImplementedException();
}
}
But how would I actually create an instance of the concrete class at runtime?
The problem is that DataOperator<A> and DataOperator<B> are not assignment compatible. Not even if A and B are. So, you cannot assign your classes to, say DataOperator<object>. Therefore, you will have to treat them individually as non related types.
A way out is to have a non generic base type or interface.
interface IDataOperator
{
public void DoSomething(IList data);
}
We create an abstract class that implements it explicitly in order to hide this weakly typed DoSomething when not called through the interface. We also introduce the generic type parameter.
abstract class DataOperator<T> : IDataOperator
where T : class
{
void IDataOperator.DoSomething(IList data)
{
if (data is IList<T> listT) {
DoSomething(listT);
} else {
throw new ArgumentException("The List is not compatible.", nameof(data));
}
}
abstract public void DoSomething(IList<T> data);
}
We implement concrete types like this:
class DataOperatorA : DataOperator<MyClassA>
{
public override void DoSomething(IList<MyClassA> data)
{
throw new NotImplementedException();
}
}
class DataOperatorB : DataOperator<MyClassB>
{
public override void DoSomething(IList<MyClassB> data)
{
throw new NotImplementedException();
}
}
These implementations are assignment compatible to our interface. Example:
IDataOperator[] operators = { new DataOperatorA(), new DataOperatorB() };
If you want to create different operators depending on other data, you can create a factory class. In this example, we use a string as discriminator, but it could be anything else, like a System.Type or an enum, etc.
static class DataOperator
{
public static IDataOperator Create(string op)
{
return op switch {
"A" => new DataOperatorA(),
"B" => new DataOperatorB(),
_ => throw new ArgumentException("Unknown operator.", "op")
};
}
}
Same example as above but with the factory:
IDataOperator[] operators = { DataOperator.Create("A"), DataOperator.Create("B") };
I resolved this issue using a factory as suggested by Matthew Watson.
DataOperator is actually AggregateRootMigrator
public static class AggregateRootMigratorFactoryProvider
{
public static AggregateRootMigrator<T> GetAggregateRootMigrator<T>()
where T : AggregateRoot
{
var type = typeof(AggregateRootMigrator<T>).Assembly.GetTypes().Where(
t =>
{
if (t.IsAbstract == false && t.IsSubclassOf(typeof(AggregateRootMigrator<T>)))
{
return true;
}
return false;
}).SingleOrDefault();
if (type == null)
{
throw new InvalidOperationException($"No Factory found for eventType: {typeof(T).Name}");
}
return (AggregateRootMigrator<T>)Activator.CreateInstance(type);
}
}
now I can use it like this:
var dataMigrator = AggregateRootMigratorFactoryProvider.GetAggregateRootMigrator();
var result = dataMigrator.Migrate(data);

How to upcast using Generic Type Class to Formal Implementation?

When we try to upcast from a Generic Type class to a formal implementation it gives a casting error.
In the code below you can see that I have a FormalClass that is an implementation of a GenericTypeClass. When I try to up cast from the GenericTypeClass to a FormalClass it it gives this error:
"[System.InvalidCastException: Unable to cast object of type 'GenericTypeClass`1[TestType]' to type 'FormalClass'.]"
I know that this will not work but if you need to do an up cast what is the best way to solve it? Automapper? Json serialization? Other?
Below is a dotnetfiddle ( https://dotnetfiddle.net/LLg0vp ) example:
using System;
public class Program
{
public static void Main()
{
var a = new GenericTypeClass<TestType>();
var b = a as FormalClass;
if (b == null)
Console.WriteLine("'a as Formal' Is NULL");
try
{
var c = (FormalClass)a;
}
catch (Exception ex)
{
Console.WriteLine("'(FormalClass)a' gives this error: " + ex.Message);
}
}
}
public class FormalClass : GenericTypeClass<TestType>
{
}
public class GenericTypeClass<T>
where T : class, IType
{
}
public class TestType : IType
{
}
public interface IType
{
}
You can't accomplish this with inheritance. Once an object is created with a type of GenericTypeClass<TestType> it can never become a FormalClass.
Options:
Investigate ways to create a FormalClass instead of a
GenericTypeClass<TestType>.
This could be simple or complex depending on the flow of your code.
Create a new FormalClass and use Automapper to copy property values into it
Changes to a property in the new FormalClass object would have no effect on the original Generic object.
Instead of making FormalClass inherit from GenericTypeClass<TestType>', make it a wrapper for aGenericTypeClass' and pass in the `GenericTypeClass' in the constructor.
Any new property added to the Generic class would have to be added to the FormalClass
I have included a code sample for the wrapper method.
using System;
public class Program
{
public static void Main()
{
var a = new GenericTypeClass<TestType>();
var b = new FormalClass(a);
a.Name = "NameA";
b.Name = "NameB";
Console.WriteLine(a.Name);
Console.WriteLine(b.Name);
}
}
public class FormalClass
{
GenericTypeClass<TestType> _inner;
public FormalClass(GenericTypeClass<TestType> parameter)
{
_inner = parameter;
}
public string Name
{
get
{
return _inner.Name;
}
set
{
_inner.Name = value;
}
}
}
public class GenericTypeClass<T>
where T : class, IType
{
public string Name
{
get;
set;
}
}
public class TestType : IType
{
}
public interface IType
{
}
You example can be simplified as follows (note that generics don't have anything to do here):
void Main()
{
var a = new BaseClass();
var b = a as DerivedClass;
if (b == null)
Console.WriteLine("'a as Derived' Is NULL");
}
public class BaseClass
{
}
public class DerivedClass : BaseClass
{
}
...and sure enough, that's never going to work. Derived classes can be casted back to the base class, but not the other way around.

Abstract factory pattern instead of generics - how?

I have a generic interface:
public interface IReader<T> where T: Result
{
IEnumerable<T> ReadResults();
}
where Result is a base class and is extended into DetailedResult:
public class Result
{
// ...
}
public class DetailedResult : Result
{
// ... ...
}
Now I have two concrete types for IReader, each of this implementation returns different type, specific to the reader type:
public class DefaultResultReader<Result> : IReader<Result>
{
IEnumerable<Result> ReadResults();
}
and
public class DetailedResultReader<DetailedResult> : IReader<DetailedResult>
{
IEnumerable<DetailedResult> ReadResults();
}
The structure presented above uses generics. I would like to get rid of it if possible, and have some kind of a factory which would create a concrete implementation of IReader for me - DefaultResultReader.ReadResults() method must return Result while DetailedResultReader.ReadResults() must return DetailedResult
My question is how should the abstract factory look for this structure - how to design it so that I can create specific IReader object as requested ?
i didn't get exactly what you want, but i guess you expect something the following :
public interface IReader<T> where T : Result
{
IEnumerable<T> ReadResults();
}
public class Result
{
}
public class DetailedResult : Result
{
// ... ...
}
public class DefaultResultReader : IReader<Result>
{
public IEnumerable<Result> ReadResults()
{
return null;
}
}
public class DetailedResultReader : IReader<DetailedResult>
{
public IEnumerable<DetailedResult> ReadResults()
{
return null;
}
}
public abstract class ResultReaderAbsractFactory
{
public abstract IReader<Result> CreareDefaultResultReader();
public abstract IReader<DetailedResult> CreareDetailedResultReader();
}
public class ConcreteResultRaderFactory : ResultReaderAbsractFactory
{
public override IReader<Result> CreareDefaultResultReader()
{
return new DefaultResultReader();
}
public override IReader<DetailedResult> CreareDetailedResultReader()
{
return new DetailedResultReader();
}
}
If the DefaultResultReader<Result> will always return IEnumerable<Result>, and DetailedResultReader<DetailedResult> will always return IEnumerable<DetailedResult>, I would suggest making the classes
public class DefaultResultReader : IReader<Result>
{
IEnumerable<Result> ReadResults();
}
and
public class DetailedResultReader : IReader<DetailedResult>
{
IEnumerable<DetailedResult> ReadResults();
}
You then have the abstract factory class
public class ReaderFactory
{
public IReader<Result> CreateDefaultResultReader()
{
return new DefaultResultReader();
}
public IReader<DetailedResult> CreateDetailedResultReader()
{
return new DetailedResultReader();
}
}
If you want to make it fully generic, meaning that you do not have to extend this class even if you create new reader types. You can simply make something like this :
public static class ResultReaderFactory
{
public static IEnumerable<T> ReadResults<T>() where T : Result
{
IReader<T> reader = GetReader<T>();
if(reader != null)
{
return reader.ReadResults();
}
return null;
}
public static IReader<T> GetReader<T>() where T : Result
{
// get the first reader implementation from the list
// that matches the generic definition
IReader<T> reader = _instances
.FirstOrDefault(
r => r.GetType()
.GetInterfaces()
.Any(
i => i == typeof(IReader<T>)
)
) as IReader<T>;
return reader;
}
// placeholder for all objects that implement IReader
static IEnumerable<object> _instances;
static ResultReaderFactory()
{
// register all instances of classes,
// that implements IReader interface
_instances = typeof(ResultReaderFactory)
.Assembly
.GetTypes()
.Where(
t => t.GetInterfaces()
.Any(
i => i.Name
.StartsWith("IReader`1")
)
)
.Select(t => Activator.CreateInstance(t));
}
}
To use this you just have to make classes that implements IReader<T> in the same Assembly that ResultReaderFactory is. Then you can just forget about that factory object and simply call it whenever you want with :
ResultReaderFactory.GetReader<DetailedResult>();
// or assuming you've created class ExtremalyDetailedResult
// and ExtremalyDetailedResultReader
ResultReaderFactory.GetReader<ExtremalyDetailedResult>();
This will read all types that implements IReader<T> whenever you start your application. Then it will pack all of those classes ( already instantiated ) in to the List<object> so you can use them later on. This is really slow though because it uses reflections and Linq to determine which IReader<T> implementation to return.
try this online

How to return a class with a generic type by passing in the type

I have a class which uses a generic type,
public class BaseClass<T> {
public T Data { get; set; }
public BaseClass(T data) {
this.Data = data;
}
public BaseClass() { }
}
I want to create a method that returns a BaseClass<T> object, so I'm trying this:
public BaseClass<T> NoData() {
return new BaseClass<T>(null);
}
and call it with something like return NoData<MyTClass>();
I'm getting an error tho with the <T>, The type or namespace 'T' cannot be found
Is this possible to do in c#? Thanks!
You just need to add a generic parameter to the method name:
public BaseClass<T> NoData<T>() {
return new BaseClass<T>(null);
}
But since you don't specify that T is a class, you need to use the more general default(T):
public BaseClass<T> NoData<T>() {
return new BaseClass<T>(default(T));
}
And since you have a default constructor that essentially does the same thing you could also do:
public BaseClass<T> NoData<T>() {
return new BaseClass<T>();
}

Passing Enums as parameter from abstract class

I have an abstract base class, TestFactory which looks like:
public abstract class TestFactory
{
//static method that can create concrete factories
public static TestFactory CreateTestFactory(FactoryType factoryType)
{
TestFactory factory = null;
switch (factoryType)
{
case FactoryType.Blood:
factory = new BloodTestFactory();
break;
case FactoryType.Urine:
factory = new UrineTestFactory();
break;
default:
break;
}
return factory;
}
//BloodTestFactory and UrineTestFactory are concrete types
//that will need to create their own tests
//this enum parameter needs to 'switch' between
//BloodTestType and UrineTestType
public abstract LabTest CreateTest(Enum e);
}
public enum FactoryType
{
Blood,Urine
}
So this class creates a concrete factory like:
public class BloodTestFactory :TestFactory
{
//both BloodTestFactory and UrineTestFactory will create a LabTest object
//I would like to have a BloodTestType and UrineTestType enum, what do I need
//to do to pass a generic Enum as a parameter and then switch on BloodTestType
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
//switch (e)
//{
// default:
// break;
//}
//creation logic here
}
}
public enum BloodTestType
{
H1AC,Glucose
}
A BloodTest itself is an abstract class which will return a concrete BloodTest object based on the Enum value. For clarity's sake I would like to have a BloodTestType and a UrineTestType (not shown) enum. Since the CreateTest method is abstract, how can I make sure that I can pass it a BloodTestType when I want to create BloodTests and a UrineTestType enum when I want to create UrineTest?
I'm not sure if this is the best approach to take for this requirement, I'll leave the design pattern discussion for comments / other answers.
I wouldn't necessarily do it this way, however, to make the code you have work, I would introduce a class level generic parameter on TestFactory for the enum.
public abstract class TestFactory<TTestType>
{
public abstract LabTest CreateTest(TTestType testType);
}
Derived classes then simply specify the generic argument:
public class BloodTestFactory : TestFactory<BloodTestType>
{
public override LabTest CreateTest(BloodTestType e)
{
}
}
Note that unless you use something like Unconstrained Melody you don't get much support for generic type constraints on enum.
Also note that this now makes it difficult to reference the shared base class because you need to close the generic argument:
TestFactory baseReference = myBloodTestFactory; // Not possible.
TestFactory<BloodTestType> baseReference = myBloodTestFactory;
Personally I'd likely decompose these two factories into separated classes without a base, or look into using an interface. Dealing with specific parameters in what you would like to have as "common" methods is difficult.
There is a nice way of doing this, and it results in code such as:
var client = new LabTestClient();
client.Run<BloodTestFactory,BloodTestType>(BloodTestType.H1AC);
client.Run<BloodTestFactory,BloodTestType>(BloodTestType.Glucose);
// outputs
// BloodTest: H1AC
// BloodTest: Glucose
Here is the rest of the code, hopefully its quite self explanatory how to use it/extend it to your needs - there are concrete classes for each type of lab test.
First the client and the abstract classes
public class LabTestClient
{
public void Run<TFactory, TInput>(TInput input) where TFactory : LabTestFactory, new()
{
LabTestFactory factory = new TFactory();;
LabTest labTest = factory.CreateLabTest();
labTest.Run(input);
}
}
public abstract class LabTest
{
public abstract void Run<TInput>(TInput input);
}
public abstract class LabTestFactory
{
public abstract LabTest CreateLabTest();
}
Then the concrete implementation:
public enum BloodTestType{ H1AC,Glucose }
public class BloodTest: LabTest
{
public override void Run<TInput>(TInput input)
{
Console.WriteLine("BloodTest: {0}",input);
}
}
public class BloodTestFactory : LabTestFactory
{
public override LabTest CreateLabTest()
{
return new BloodTest();
}
}
public enum UrineTestType{ A,B }
public class UrineTest: LabTest
{
public override void Run<TInput>(TInput input)
{
Console.WriteLine("UrineTest: {0}",input);
}
}
public class UrineTestFactory : LabTestFactory
{
public override LabTest CreateLabTest()
{
return new UrineTest();
}
}
A live example: http://rextester.com/MUV89315
However, this is still not ideal, as the individual tests still don't enforce their input - and in fact when you come to do anything complex within the test you'll find you don't know what the actual type of TInput is unless you cast it to the right enum:
public class UrineTest: LabTest
{
public override void Run<TInput>(TInput input)
{
var urineTestType = (UrineTestType)input;
// do something useful.
}
}
Just test for type safety in your overriden method:
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
Just add an argument check to your base class:
public abstract class TestFactory
{
//static method that can create concrete factories
public static TestFactory CreateTestFactory(FactoryType factoryType)
{
if (!Enum.IsDefined(typeof(FactoryType), factoryType)
{
throw InvalidEnumArgumentException(...);
}
TestFactory factory = null;
switch (factoryType)
{
case FactoryType.Blood:
factory = new BloodTestFactory();
break;
case FactoryType.Urine:
factory = new UrineTestFactory();
break;
default:
break;
}
return factory;
}
//...
}

Categories