web-dev-qa-db-ja.com

.NET 4.0(C#)で動的にインターフェイスを実装する

.NET 4.0の新しい動的機能を使用すると、インターフェースを動的に実装できるようになるはずです。与えられた:

public interface IFoo 
{
    string Bar(int baz);
}

public class Foo : IFoo
{
    public string Bar(int baz) { return baz.ToString(); }
}

public class Proxy : IDynamicMetaObjectProvider
{
    private readonly object target;

    public Proxy(object target) { this.target = target; }

    // something clever goes here
}

それから私は書くことを可能にするいくつかの方法があることを望んでいます:

dynamic proxy = new Proxy(new Foo());
IFoo fooProxy = (IFoo)proxy; // because the target object implements it
string bar = fooProxy.Bar(123); // delegates through to the target implementation

しかし、今のところ、何を置き換えるかわかりません// something clever goes hereあり。

だから、私の質問は:

  1. これは実際に動的ランタイムで実行できますか?メソッドやプロパティのようなものを動的に実装することはかなり簡単なようですが、動的に実装するインターフェースとそれらへの変換についてのドキュメントは見つかりませんでした。

  2. これが可能であると仮定すると、それはどのくらい難しいでしょうか? (私は、リフレクションなどの経験が豊富で、ダイナミックフレームワークの初心者である、まともなプログラマーであると想定できます。)

  3. このようなものを実装するための正しい方向に私を向けるのに役立つリソースはありますか?または、このようなことがすでに行われているサンプルでさえ、開始点として使用できますか?

47
Greg Beech

私の知る限り、インターフェイスメンバーをラップされたインスタンスに転送するコードを記述または生成することは、手動の介入なしには不可能です。この種のものに対するマイクロソフト提供のサポートを見たい場合は、 https://connect.Microsoft.com/VisualStudio/feedback/details/526307/add-automatic-generationで投票することを検討してください。 -of-interface-implementation-via-implementing-member

13
Nicole Calinoiu

オープンソースフレームワーク Impromptu-Interface は、これを行うために設計されました。静的インターフェイスを備えたキャッシュされた軽量プロキシを生成し、dlrを使用して呼び出しを元のオブジェクトに転送します。

using ImpromptuInterface;

public interface ISimpeleClassProps
{
    string Prop1 { get;  }

    long Prop2 { get; }

    Guid Prop3 { get; }
}

-

dynamic tOriginal= new ExpandoObject();
tOriginal.Prop1 = "Test";
tOriginal.Prop2 = 42L;
tOriginal.Prop3 = Guid.NewGuid();

ISimpeleClassProps tActsLike = Impromptu.ActLike(tOriginal);
42
jbtule

私はあなたが望むことを行うライブラリを書いたと思います...それはDynamicWrapper(CodePlex上)と呼ばれ、それは自動的にクラスをラップしてインターフェイスを実装します。 これでよろしいですか?

7
Brian Genisio

明示的なキャスト、as、およびisは、プロキシ基本クラスに対する型の比較のために失敗しますが、暗黙的なキャストは、DynamicObject.TryConvertをトリガーして、次の代わりに内部オブジェクトを返すことができます。動的オブジェクト。
- TryConvert MSDNドキュメント

以下のコードは機能しますが、これはそれ自体がインターフェースの委任ではなく、内部状態の公開のみです。ブライアンのDynamicWrapperなどの遮断パターンのようなものを探しているようです。

dynamic wrapper = new Proxy(new Foo());
IFoo foo = wrapper;
foo.Bar();

class Proxy : DynamicObject
{
    ...

    public override bool TryConvert(ConvertBinder binder, out object result)
    {
        Type bindingType = binder.Type;
        if (bindingType.IsInstanceOfType(target))
        {
            result = target;
            return true;
        }
        result = null;
        return false;

    }

}
3
stephbu

@jbtuleからの回答を補完する実行時に動的オブジェクトを作成し、目的のインターフェイスを実装できるようにするCustomActivatorを作成しました。私は Impromptu-Interface framework を使用してそれを実現しています。

呼び出しは簡単です:

CustomActivator.CreateInstance<MyInterface>();

github に入れました。

2