Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a type to instantiate a derived class which uses restricted generics

Tags:

c#

generics

I'm using a generic factory class where the generic part is the derived class that is being used. The normal usage is clear: BaseClass<DerivedA> C = new BaseClass<DerivedA>(). Now though I'm trying to put in property injection into the class where I use these classes. To do that I tried to give Type as a Parameter (so that I can inject which derived class is being used).

Now though I'm a bit at a loss despite looking for examples and trying around myself. And I'm now wondering: Is such a construct possible at all to use? And if so how can I instantiate the class and use Exists and ExistsB?

Usage:

public class MyMainClass
{
    object _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>

    public MyyMainClass(Type typeIWant)
    {
          .....
    }
}

....
MyMainClass a = new MyMainClass(typeof(DerivedA));
MyMainClass b = new MyMainClass(typeof(DerivedB));

Generic class:

public abstract class BaseClass<T> where T: BaseClass<T>, new()
{
...
    public bool Exists(int a) {...}
}

Derived class:

public class DerivedA :BaseClass<DerivedA>
{
...
}

public class DerivedB :BaseClass<DerivedB>
{
...
   public bool ExistsB(string a) {...}
}
like image 683
Thomas Avatar asked Apr 04 '18 08:04

Thomas


2 Answers

You can create an instance of any type you pass with this:

_ClassInstance = Activator.CreateInstance(typeIWant)

It isn't recommended though, because you will be forever checking its type and casting it when you want to use one of the BaseClass methods. If you are able to change your main class to take a type parameter, it should look like this:

public class MyMainClass<T> where T: BaseClass<T>, new()
{
    T _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>

    public MyMainClass()
    {
        _ClassInstance = new T();
    }
}

This will allow you to use any methods defined on BaseClass. Given you want to use ExistsB, which isn't, you will still need to check its type at run-time and cast it. I would recommend something like this:

if (_ClassInstance is DerivedB derivedB)
    derivedB.ExistsB("...");

If you really need compile-time checking, and I would recommend it, your classes will need to change. You can't access a method or property defined on a derived class with a reference to the base class only.

like image 62
andrensairr Avatar answered Oct 14 '22 23:10

andrensairr


Is this what you want?

Object instance1 = Activator.CreateInstance<Object>();
Object instance2 = Activator.CreateInstance(typeof(object));
like image 26
1pgjy Avatar answered Oct 14 '22 23:10

1pgjy