Velvet Star Monitor

Standout celebrity highlights with iconic style.

general

Why does the evaluation of Expression.TypeAs return an object of the underlying concrete type and not the interface I've requested it to?

Writer Mia Lopez

The actual answer is in the comments on the answer. I was expecting to get an 'instance' of my interface, which you can't do.

--

I found a way to do what I actually wanted, which for anyone interested, I've outlined below.

public interface Interface<T> { Func<T,T> Property { get; set; } }
public class Concrete : Interface<string>
{ public Concrete() { (this as Interface<string>).Property = (s) => { return $"hello, {s}!"; }; } Func<string, string> Interface<string>.Property { get; set; }
}
class Program
{ static void Main(string[] args) { object obj = new Concrete(); var propInfo = obj.GetType().GetInterfaces().Single().GetProperty("Property"); dynamic func = propInfo.GetMethod.Invoke(obj, null); var output = func("world"); }
}

--

I'm doing some codegen and am making heavy use of dynamic types and unfortunately I've hit the dynamic type/explicit interface conundrum.

I can get around this by using Convert.ChangeType(...) as outlined here but it requires that IConvertable is implemented which will have a large overhead that I don't want to have to do.

I've found an example of using Linq expressions to do this using either Expression.TypeAs or Expression.Convert, however this always returns the underlying concrete type and not the interface I need.

Here's a code example of what I'm trying to do:

namespace ExpressionCasting
{ public interface Interface<T> { void Method(T t); } public class ImplementedInterface : Interface<string> { void Interface<string>.Method(string t) { } } class Program { static void Main(string[] args) { var implementedInterface = new ImplementedInterface(); // type is an IInterface<string> var type = implementedInterface.GetType().GetInterfaces().Single(); // i is always an ImplementedInterface var i = Convert(type, implementedInterface); // i is always an ImplementedInterface Console.WriteLine(i.GetType()); // i want this to be an IInterface<string> nit and ImplementedInterface. } static object Convert(Type type, object subClass) { var body = Expression.TypeAs( Expression.Constant(subClass, subClass.GetType()), type); var run = Expression.Lambda( body, Expression.Parameter(subClass.GetType())).Compile(); return run.DynamicInvoke(subClass); } }
}

Any ideas how I can get what I need with expressions or if there is another option I haven't thought of?

3

3 Answers

The issue isn't with your expression. It's with the use of dynamic. The DLR isn't looking at explicit interface implementations. It's easy to prove since the following code returns the same exception:

dynamic i = new ImplementedInterface();
i.Method(); // throws exception as method is not found.

Here is a small article on the issue as well as other surprises when using dynamic:

6

You are returning an object and pushing it into a dynamic parameter. It is going to go with the simplest possible cast, which is ImplementedInterface, not Interface. You are effectively undoing the cast done in your Convert method by down casting to type object and then invoking as a dynamic variable.

Your expression looks good. But there is an issue with dynamic itself.

Even it this case (see below) you will have an error:

public interface Interface<T> { void Method(T t); }
public class ImplementedInterface : Interface<string> { void Interface<string>.Method(string t) { } }
void Main()
{ dynamic i = (Interface<string>)new ImplementedInterface(); i.Method(); // throws exception as method is not found.
}

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.