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?
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: http://csharpindepth.com/Articles/Chapter14/DynamicGotchas.aspx