为什么Expression.TypeAs的评估返回底层具体类型的对象而不是我请求它的接口?

Sim*_*iss 4 c# reflection expression-trees

实际答案在答案的评论中.我期待得到我的界面的"实例",你不能这样做.

-

我找到了一种方法来做我真正想要的,对于任何有兴趣的人,我已在下面概述.

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");
    }        
}
Run Code Online (Sandbox Code Playgroud)

-

我正在做一些codegen并且正在大量使用动态类型,不幸的是我遇到了动态类型/显式接口难题.

我可以通过使用这里Convert.ChangeType(...)概述的方法解决这个问题,但是它要求实现这一点,这将产生很大的开销,我不想这么做.IConvertable

找到了一个例子使用LINQ表达式使用这个无论是做Expression.TypeAs还是Expression.Convert,然而,这总是返回底层的具体类型,而不是我所需要的接口.

这是我正在尝试做的代码示例:

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);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

任何想法我怎么能得到我需要的表达式或如果有其他选项我没有想到?

Mik*_*rry 5

问题不在于你的表达.这是动态的使用.DLR没有考虑显式接口实现.由于以下代码返回相同的异常,因此很容易证明:

dynamic i = new ImplementedInterface();
i.Method(); // throws exception as method is not found.
Run Code Online (Sandbox Code Playgroud)

这里有一篇关于这个问题的小文章以及使用动态时的其他惊喜:http://csharpindepth.com/Articles/Chapter14/DynamicGotchas.aspx