0

文字列を介して動的な c# オブジェクトで関数を呼び出すことができるかどうか疑問に思っていました。私はこのようなことをしたい:

string lMethodName = "MethodName";
dynamic lDynamicObject = GetDynamicObject();
lDynamicObject.Invoke(lMethodName, lParameters);

どんな考えや解決策も大歓迎です。

たぶん、Servy が言ったように、私たちが望むものを別のデザインで達成するためのより良い方法がある. SignalR を使用しており、ダッシュボード Web アプリがあります。ダッシュボード内の各ウィジェットに、データをプッシュできる機能を持たせたいと考えています。これを実現するために、レーザー コードを使用して、ウィジェット ID を個々のウィジェットの SignalR クライアント側プロキシに挿入します。各ウィジェットには次のようなものがあります。

hub.client.updateWidget123456 = aUpdateFunction;

123456 はウィジェットの ID です。サーバー側の SignalR ハブ コードでは、クライアント側の JavaScript 関数にコールバックできます。

int lWidgetId = 123456;
dynamic lDynamic = Clients.All;
lDynamic.Invoke("updateWidget" + lWidgetId, lParameters);

JavaScript プロキシ メソッドを作成せずにこれを実装する方法は他にも考えられます。サーバーは個々のウィジェットと直接通信回線を持っていたので、これはいいと思いました。複数のダッシュボード/ブラウザーからアクセスできますが、上記の 1 回の呼び出しですべて更新されます。

代わりに、すべてのウィジェットとそれらに情報を送信する方法を知っている JavaScript クライアント側コードで他のオブジェクトを呼び出すことで、これを実装できます。これは SignalR のハブ アーキテクチャに反するものであり、これを行うことで車輪を再発明しているように感じました。

より良い設計アプローチについて考えている人はいますか? 助けてくれてありがとう、そしてこの議論を引き起こしたあなたのコメントServyに感謝します。

また、この質問は重複していません。もう 1 つの質問は、Paul が以下でコメントしたような動的オブジェクトに関するものではありません。

4

4 に答える 4

2

リフレクションを使用してメソッドを呼び出すことができるのdynamicは、それが通常の C# オブジェクトであることがわかっている場合 (つまり、特別なランタイム バインダーがない場合) だけです。

動的に使用できるプロパティ バッグを実装する次のクラスを考えてみます。

public class PropertyBag : DynamicObject
{
    private Dictionary<string, object> _propertyBag = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _propertyBag.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _propertyBag[binder.Name] = value;
        return true;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return base.GetDynamicMemberNames();
    }
}

次のことを行うことは完全に有効です。

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow";
propertyBag.Value = 42;

ただしPropertyInfo、これらの動的プロパティのいずれかを取得しようとすると、PropertyBagクラスがそれらを実装していないため失敗します。

public static void SetProperty(dynamic propertyBag, string propertyName, object value)
{
    PropertyInfo property = propertyBag.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
    if (property == null)
    {
        throw new NotImplementedException();
    }

    MethodInfo setProperty = property.GetSetMethod();
    setProperty.Invoke(propertyBag, new object[] { value });
}

これは例外をスローします:

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow;      // works as expected
SetProperty(propertyBag, "Value", 42);  // throws a NotImplementedException

この例では、実装が簡単なプロパティを使用しましたが、明らかに同じことがメソッドにも当てはまります。この理由はdynamic、実行時に動的に評価されますが、リフレクションは静的実装にしか反映できないためです。(クラスでどのプロパティをGetProperties返す必要がありPropertyBagますか?)

通常の C# オブジェクトで使用dynamicしている場合、リフレクションは期待どおりに機能しますが、対処しているランタイム バインダーの種類と、それが内部でどのように実装されているかがわからない場合は、それに頼ることはできません。

于 2013-04-18T20:16:55.323 に答える
1

短い答え、はい、次のようなことができます:

        class MyClass { public void Action() { Console.WriteLine("Do action"); } }
        // ...
        dynamic instance = new MyClass();
        instance.GetType().GetMethod("Action").Invoke(instance, null);

ただし、この場合、インスタンスが動的型であるという事実はまったく何もしません。タイプを使用することができobject、同じように機能します。チェーンの最初のメソッドである GetType() は を返し、typeof(MyClass)そこから先は昔ながらのファッション リフレクションです。

dynamic キーワードを使用すると、これを行うことができます。これは、実行時の柔軟性がわずかに低下しますが、はるかに興味深いものです。

        dynamic instance = new MyClass();
        instance.Action();

これにより、実行時にリフレクションを使用してアクションが検索されます。この例では、 がここで設定されているため、dynamic動作が異なることは明らかではありませんが、インスタンスにその名前のメソッドがある限り、2 行目を使用して action という名前の任意のメソッドを実行できます。varMyClass

于 2013-04-18T18:56:46.307 に答える