Converting Expression<Func<BaseType,object>> to Expression<Func<DerievedType,object>>>

Viewed 178

I have a situation where in, I would like to convert an Expression<Func<BaseType,object>> to Expression<Func<DerievedType,object>> I am also open to other solutions as well for this particular scenario.

To demonstrate the problem, i have base class as following

public class PersonBase
{
    public string Name{get;set;}

    public virtual void Save()
    {
        Dummy.Method1(this,x=>x.Name);
    }
}

Derieved Class is defined as

public class Student:PersonBase
{
    public string School{get;set;}
}

The Dummy class and associated methods are defined as

public class Dummy
{

public static void Method1<TDestination>(TDestination value,params Expression<Func<TDestination,object>>[] selector)
{
    var destinationType = value.GetType();
    var selectorType = selector.GetType();

    Console.WriteLine("Destination Type : " + destinationType.ToString());
    Console.WriteLine("Selector Type : " +selectorType.ToString());


    var FinalMethodToCallInfo = typeof(Dummy).GetMethod("FinalMethodToCall", BindingFlags.Public | BindingFlags.Static);
    var FinalMethodToCallMethod = FinalMethodToCallInfo.MakeGenericMethod(destinationType);
    FinalMethodToCallMethod.Invoke(null, new object[] { selector });
}

public static void FinalMethodToCall<TDestination>(params Expression<Func<TDestination,object>>[] selector)
{
    Console.WriteLine("Finally here");
}
}

The whole example is demonstrated in the Fiddle here.

Since the destinationType in Method1 is of Type Student and selectorType is of type Expression>, I get an exception when i attempt to invoke the FinalMethodToCall using reflection.

Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[PersonBase,System.Object]][]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[Student,System.Object]][]'.

I am slightly lost here. One solution I could think of was to use ExpressionVisitor to replace the Expression Parameter Type from BaseClass to DerievedType.

But I was curious to know why, when calling the method from Base (and passing expression), I was pointing to two different types (Derieved and Base). Could someone guide me in understanding this behavior and also if there is a better solution than using ExpressionVisitor to replace the Parameter Type ?

PS: I cannot change signature of my Save Method.

1 Answers

I have made few changes to generic methods as below.

Update PersonBase and make Save method to explicitly declare T.

public class PersonBase
{
    public string Name{get;set;}

    public virtual void Save<T>() where T : PersonBase
    {
        Dummy.Method1<T>(this,x=>x.Name);
    }
}

Update Method1's first parameter to be Object like below.

public static void Method1<TDestination>(Object value,params Expression<Func<TDestination,object>>[] selector)

And call your Save with explicitly passing generic value like as follow.

(new Student{Name="anu"}).Save<Student>();
Related