0

前回ここで質問したのはずっと前のことです:)必要なものを実装するためのアイデアがないので、もう一度質問する時が来ました...

注意すべき重要な点の 1 つ - 私は Windows Phone 7.5 用のアプリケーションを作成していますが、これは Silverlight 3.0 に相当するため、提案された機能の一部はそこで動作しません (iClientMessageInspector が SL 3.0/WP7.5 にない、または動作しないなど)。リフレクションを使用して、一部のクラスのプライベート フィールドを設定します - これは重要なことです)。

OK、私の目標は、生成された Web サービス プロキシ クラスのイベント名が「Completed」で終わるすべてのイベントをサブスクライブし、Web 操作が例外で失敗するかどうかを理解することです (つまり、エラーを処理する場所を 1 か所にすることが目標です)プロジェクト内のすべての Web サービスから - たとえば、ユーザーはセッション終了のために認証されていません)。

すべての Web サービス クライアントを作成するためのクラスが 1 つあります (私のプロジェクトには約 4 つの Web サービス参照があります)。 -サービスの種類。このクラス名は WebManager で、次のような Web サービスを作成するプロパティ (1 つの Web サービス タイプに対して 1 つのプロパティ) が含まれています。

    public SomeServiceReference.AuthenticationServiceClient AuthenticationService
    {
        get
        {
            var web = new SomeServiceReference.AuthenticationServiceClient();  
            // here i plan to subscribe to xxxCompleted event 
            // i'll provide final code below            
            return web;
        }
    }

生成された Web サービス プロキシ クラス (Reference.cs) には、いくつかのイベントがあり、Web 操作が終了するたびに発生し、すべてこのパターンで名前が付けられています: "Web_service_OperationName" + "Completed"、サンプル:

public event System.EventHandler<SomeOperationCompletedEventArgs> SomeOperationCompleted;

言及すべきもう 1 つの重要なこと: SomeOperationCompletedEventArgs は標準の System.ComponentModel.AsyncCompletedEventArgs から継承されるため、WebManager クラスでいくつかのメソッドを記述し、それをデフォルトのイベント ハンドラーとして使用できます。

public void TestEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    // analyze web-call results here: 
    // do we have exception or web-operation completed successfully
    // if (e.Error != null) { /*do something there*/  }
}

したがって、SomeOperationCompleted イベントをサブスクライブし、操作が失敗するかどうかを理解するために、次のようなことができます。

    public SomeServiceReference.AuthenticationServiceClient AuthenticationService
    {
        get
        {
            var web = new SomeServiceReference.AuthenticationServiceClient();  
            web.SomeOperationCompleted += TestEventHandler;          
            return web;
        }
    }

このアプローチは問題なく機能し、TestEventHandler メソッドにブレークポイントを配置すると、「e」パラメーターに操作の詳細が表示されます。

しかし、Reference.cs のすべてのイベントのすべてのイベント サブスクリプションを記述するのは最適な方法ではないため、自動化する方法を見つけようとしています。

次のように、Reference.cs のすべてのイベントに新しいイベント ハンドラーを追加しようとしました。

        public SomeServiceReference.AuthenticationServiceClient AuthenticationService
    {
        get
        {
            var web = new SomeServiceReference.AuthenticationServiceClient();
            var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            var type = web.GetType();
            var eventsCompleted = type.GetEvents(bindingFlags).Where(e => e.Name.EndsWith("Completed")).ToArray();
            var methodInfo = this.GetType().GetMethod("TestEventHandler");
            foreach (var eventInfo in eventsCompleted)
            {
                //Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
                Delegate handler = Delegate.CreateDelegate(typeof(System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs>), this, methodInfo);
                //eventInfo.AddEventHandler(this, handler);
                MethodInfo addHandler = eventInfo.GetAddMethod();
                Object[] addHandlerArgs = { handler };
                //var p = addHandler.GetParameters();
                addHandler.Invoke(web, addHandlerArgs);
            }
            return web;
        }
    }

System.EventHandler <SomeOperationCompletedEventArgs> delegateSomeOperationCompleted にはTestEventHandler メソッドにSystem.EventHandler <System.ComponentModel.AsyncCompletedEventArgs>パラメーター型があるため、このアプローチは機能しません。同時に、私はただ書くことができますweb.SomeOperationCompleted += TestEventHandler;

WebManager クラスでこれらのイベントをサブスクライブできるようにするには、コードをどのように変更すればよいですか?

4

1 に答える 1

0

いつものように、質問を投稿した直後に答えることができます:)

このコードは機能します:

    public void TestEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        // analyze web-call results here: 
        // do we have exception or web-operation completed successfully
        // if (e.Error != null) { /*do something there*/  }        
    }
    public SomeServiceReference.AuthenticationServiceClient AuthenticationService
    {
        get
        {
            var web = new SomeServiceReference.AuthenticationServiceClient();
            var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            var type = web.GetType();
            var eventsCompleted = type.GetEvents(bindingFlags).Where(e => e.Name.EndsWith("Completed")).ToArray();
            var methodInfo = this.GetType().GetMethod("TestEventHandler");
            foreach (var eventInfo in eventsCompleted)
            {
                Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
                MethodInfo addHandler = eventInfo.GetAddMethod();
                Object[] addHandlerArgs = { handler };
                addHandler.Invoke(web, addHandlerArgs);
            }
            return web;
        }
    }
于 2013-02-07T22:01:48.560 に答える