3

動的変数があります

dynamic d = GetSomeObject();

いつか、将来、ユーザーが私に実行する関数を送ってくれます(そのname)例:"UsersGetAll"

だから私は次のようなことをする必要があります:d.UsersGetAll()

振り返ってできます。しかし、私はDLRを使用したいと思います。

これを行う唯一の解決策は、MyObject 継承してからDynamicObject実装することTryInvokeMemberですか?

クラスを制御できない場合はどうなりますか?

4

2 に答える 2

1

振り返ってできます。しかし、私はDLRを使いたいです。

なんで?これが実際には動的に応答しない「通常の」オブジェクトであると仮定すると、ここではリフレクションが最も簡単なアプローチになります。

dynamicC#4の機能(言語機能の観点から)は、ここではまったく役に立ちません。これは、 C#ソースコード内のメンバー名の動的バインディングのみを許可します。

今、あなたはできる

  • IronPythonセッションを開始し、動的バインディングを使用してメソッドを呼び出す小さなPythonスクリプトを作成します。
  • を使用して、関連するメソッド名CSharpCodeProviderを使用してC#コードをコンパイルし、そのコードを実行します。dynamic
  • 呼び出し用に生成されたコードを見て、d.UsersGetAll()基本的にそれをエミュレートします。

これらのオプションはすべて、リフレクションよりも難しい可能性があります。必要に応じて、「通常の」オブジェクトで「通常の」メソッドを呼び出すと、実行時に名前しかわからなくなります。

于 2012-11-28T13:58:13.263 に答える
1

Jonが指摘しているように、以下は、タイプが実行時にDLRを介してメソッドを提供していると思われる場合にのみ実際に適用されます。ほとんどの単純なケースでは、反射が簡単になります。

dynamicメソッド名はわかっているがターゲットはわかっていない場合を対象としています。メソッド名がわからない場合は、注意が必要です。トリッキーな点は、おそらく、コールサイトを維持して再利用できるようにすることです(これがDLRがパフォーマンスを維持する方法です)。生意気な方法の1つは、呼び出されたメソッドを追跡する静的ユーティリティクラスです。次に例を示します。パラメータを処理する必要がある場合は、非常に面倒になることに注意してください。

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
    public object Bar() { return "I was here"; }
}
static class Program
{
    static void Main()
    {
        object obj = new Foo();
        object result = DynamicCallWrapper.Invoke(obj, "Bar");
        Console.WriteLine(result);
    }
}

static class DynamicCallWrapper
{
    // Hashtable has nice threading semantics
    private static readonly Hashtable cache = new Hashtable();
    public static object Invoke(object target, string methodName)
    {
        object found = cache[methodName];
        if (found == null)
        {
            lock (cache)
            {
                found = cache[methodName];
                if(found == null)
                {
                    cache[methodName] = found = CreateCallSite(methodName);
                }
            }
        }
        var callsite = (CallSite<Func<CallSite, object,object>>)found;
        return callsite.Target(callsite, target);
    }
    static object CreateCallSite(string methodName)
    {
        return CallSite<Func<CallSite, object, object>>.Create(
            Binder.InvokeMember(
            CSharpBinderFlags.None, methodName, null, typeof(object),
            new CSharpArgumentInfo[] {
                CSharpArgumentInfo.Create(
                     CSharpArgumentInfoFlags.None, null) }));

    }
}
于 2012-11-28T13:58:38.773 に答える