I have a factory class that returns concrete instances inheriting from an abstract type. These concrete instances also have a generic property for their data type, as each instance requires a different data type. The Data property also exists on the abstract type since it is set in the factory.
public static class FactoryClass
{
public static TType CreateNewClass<TType>(object data)
where TType : AbstractClass<object>, new()
{
var newClass = new TType {Data = data};
// do some stuff
// keep track of all created types in a list
List.Add(newClass);
return newClass;
}
private List<AbstractClass<object>> MyList = new List<AbstractClass<object>>()
}
public abstract class AbstractClass<TData>
{
internal AbstractClass()
{
// do constructor things
}
protected SomeCommonFunction()
{
// common code for abstract base class
}
public abstract void DoSomethingToData();
TData Data;
}
public class ExampleClass : AbstractClass<string[]>
{
public override void DoSomethingToData()
{
// sort the strings or something
// call the abstract code
}
}
When I try and call FactoryClass.CreateNewClass<ExampleClass>(myStringArray) I get an error that it needs to be castable to AbstractClass<object>
Is there a better way to do what I’m trying to do?
Well this is the problem:
That constraint is exactly the one the compiler is complaining about.
It sounds to me like you really want something like this:
Unfortunately that then requires you to specify both type arguments to the method – but at least it’s safe in terms of the type of data you’re using. You may be able to work around this by creating two generic methods and a separate class to be used between them, allowing you to write something like:
The
Formethod would return a generic type with a type argument ofstring[], and thenCreateNewClasswould be an instance method which took the container type for the data type.However, your list simply can’t work in its current form. You may want to create a non-generic base class for
AbstractClass:then:
At that point the list in your factory would be a
List<AbstractClass>; you wouldn’t know the data type of each entry in a compile-time-safe way… which makes complete sense as each element could use a different type.(Oh, and of course your list field will need to be static if you want to access it from a static method…)