2016-04-27 4 views
4

実際の回答は回答のコメントにあります。あなたがすることができない私のインターフェースの「インスタンス」を得ることを期待していました。Expression.TypeAsの評価が、私が要求したインタフェースではなく、基礎となる具体的な型のオブジェクトを返すのはなぜですか?

-

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"); 
    }   
} 

-

私はいくつかのコード生成をやってるとダイナミック型の多用を作っていますし、残念ながら私は、動的型/明示的なインターフェイスの難問を打ってきました。

hereのようにConvert.ChangeType(...)を使用して回避することができますが、それは私がしたくないオーバーヘッドが大きいIConvertableが実装されている必要があります。

私はExpression.TypeAsまたはExpression.Convertのいずれかを使用してこれを行うには、LINQの式を使用してのfound an exampleが、しかし、これは常に基本となる具体的なタイプではなく、私は必要なインターフェイスを返してきました。

ここで私が何をしようとしているのコード例です:

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); 
     } 
    } 
} 

すべてのアイデアは、私は私は考えていない別のオプションがある場合、私は表現で必要とするか、またはものを手に入れることができますか?

+0

あなたの期待は非常に明確ではありません - なぜインタフェースを実装するクラスのインスタンスが問題であるなりましたか?あなたが結果として期待するものは何ですか?インタフェースにはインスタンスがありません...また、Mike [回答として指摘](http://stackoverflow.com/a/36894929/477420) 'i.Method();は常にインターフェイスにこのメソッドとしてスローする - サンプルが実際に問題を示していることを確認してください。 –

+0

私はあなたが 'i.Method(" foo ");を意味すると思いますが、実際にはここで問題は変わりません。動的オブジェクトをインタフェースに変換するための素晴らしいNugetである 'ImpromptuInterface'を使っても、このような明示的な実装にはまだアクセスできません。 –

+0

BTW Convertメソッドは、パラメータを使用しないラムダボディを作成し、それをパラメータで呼び出す方法です。パラメータを作成し、定数値の代わりにTypeAsの最初のパラメータとして渡すか、Constantを引き続き使用して、lambdaパラメータとDynamicInvokeに渡されるパラメータを削除します。 (問題は変わらず、使い方を整えるだけです)。 –

答えて

5

問題はあなたの表現ではありません。それはダイナミックなものです。 DLRは、明示的なインターフェイスの実装を検討していません。 http://csharpindepth.com/Articles/Chapter14/DynamicGotchas.aspx

+0

正解であれば正解でも、タイトルで尋ねられたものとは関係がなく、「誤植」として閉じられる可能性があることを意味します... –

+0

@mikeこれは私がこのことを意味していた "残念ながら私はダイナミックタイプ/明白なインタフェースの謎 " –

+0

基本的にプライベートメソッドを呼び出すことを検討しています。 IE:MethodInfoへのリフレクトを使用する:GetMethod( "Interface .Method"、BindingFlags.Instance | BindingFlags.NonPublic)。これを可能にするには、独自のDynamicObjectを実装する必要があります。 –

1

オブジェクトを返し、動的パラメータにプッシュします。可能な限りシンプルなキャストになります。これは、InterfaceではなくImplementedInterfaceです。 Convertメソッドで行われたキャストを効果的に元に戻すには、オブジェクトを型にキャストしてから動的変数として呼び出します。

0

あなたの表現がよさそうだ:ここで

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

が動的使用して問題に関する小さな記事だけでなく、他の驚きである:それは、次のコードは、同じ例外を返しますので、証明するのは簡単です。 しかし、 dynamic自体に問題があります。

でもそれあなたがエラーになります(下記参照)この場合:

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. 
} 
関連する問題