0

很久以前我上次在这里问一个问题:) 现在是时候再问一次了,因为我没有任何想法来实现我需要的东西......

需要注意的一件重要事情 - 我正在为 Windows Phone 7.5 编写应用程序,它等于 Silverlight 3.0,因此您可能建议的某些功能在那里不起作用(比如 iClientMessageInspector 在 SL 3.0/WP7.5 中不存在,或者我不能通过使用反射设置某个类的私有字段 - 值得一提)。

好的,我的目标是订阅生成的 Web 服务代理类的每个事件,其中事件名称以“已完成”结尾,并了解 Web 操作是否因异常而失败(所以 - 目标是有一个地方来处理错误来自项目中的所有 Web 服务 - 例如,由于会话结束,用户未经过身份验证)。

我有一个类来创建所有 Web 服务客户端(在我的项目中大约有 4 个 Web 服务引用),因此只有一个方法来处理所有 Web 发起的 Web 服务调用中出现的所有异常可能很有用-服务类型。此类名称是 WebManager,它包含创建 Web 服务的属性(一种 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;

另一件重要的事情要提到: 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;
        }
    }

这种方法不像 SomeOperationCompleted 那样工作,System.EventHandler <SomeOperationCompletedEventArgs> delegate并且 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 回答