rashmatash
rashmatash

Reputation: 1819

convert/cast base type to derived generic type

In the following code, I'd like to call a method that I declared in the derived class:

class BaseClass
{
    // ...
}
class A<T> : BaseClass
{
    public void F(T args){ //... }
}
class B<T> : BaseClass
{
    // B<T> doesn't have method F()
}
///....
class myApplication
{
    // ...
    public void DoSomething(BaseClass arg)
    {
        // Now I know that arg is of type A<T> for some type T
        // but I don't know what T is. Also declaring DoSomething
        // as DoSomething<T>() is not an option.
        // 
        // I would like to call (arg as A<T>).F(...) but how can I
        // deduce T? Can it be done in any other way?
    }
}

Please read the comment in the code. How can I do something like this?

Upvotes: 1

Views: 57

Answers (1)

Markus
Markus

Reputation: 22421

In order to call the method, you can run the following code:

class myApplication
{
    // ...
    public void DoSomething(BaseClass arg)
    {
        var type = arg.GetType();
        // Check whether a generic type was passed
        if (type.IsGenericType)
        {
            var genType = type.GetGenericTypeDefinition();
            // Check whether it is of type A<>
            if (genType == typeof(A<>))
            {
                // Get generic argument type
                var genArg = type.GenericTypeArguments[0];
                // Create a default instance; might not work under all circumstances
                // Better to get the method parameter in another way
                var mthArg = Activator.CreateInstance(genArg);
                // Get method that is to be called
                var mth = type.GetMethod("F");
                // Invoke method dynamically
                mth.Invoke(arg, new object[] { mthArg });
            }
        }
    }
}

Please note that it is important to pass an argument of type T to method F. You have to prepare the value for this. In my sample, I've added a call to Activator.CreateInstance that requires T to have a public default constructor (I've used int for testing).

Upvotes: 2

Related Questions