Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据拦截和返回值自动重试客户端WCF调用_C#_Wcf - Fatal编程技术网

C# 根据拦截和返回值自动重试客户端WCF调用

C# 根据拦截和返回值自动重试客户端WCF调用,c#,wcf,C#,Wcf,是否可以拦截WCF调用的结果并重试该操作 例如,操作的返回值可能包含一个状态代码,该代码指示我传递给原始调用的会话令牌已过期。在这种情况下,我可以检索一个新的会话令牌,然后使用新的会话令牌重试调用 是否可以通过使用WCF截取返回值、检查返回值,然后对操作调用方完全透明地重试调用来执行此重试操作 我已经知道如何使用IParameterInspector检查调用,但目前还没有内置的方法来重试调用 我正在寻找一种使用纯拦截的方法,这样它对客户端完全透明。您可以使用AOP框架来实现这一点。Unity有足

是否可以拦截WCF调用的结果并重试该操作

例如,操作的返回值可能包含一个状态代码,该代码指示我传递给原始调用的会话令牌已过期。在这种情况下,我可以检索一个新的会话令牌,然后使用新的会话令牌重试调用

是否可以通过使用WCF截取返回值、检查返回值,然后对操作调用方完全透明地重试调用来执行此重试操作

我已经知道如何使用
IParameterInspector
检查调用,但目前还没有内置的方法来重试调用


我正在寻找一种使用纯拦截的方法,这样它对客户端完全透明。

您可以使用AOP框架来实现这一点。Unity有足够的功能,或者您可以考虑使用一个“适当”的AOP框架,比如LIFU或PASTHARP。

< P>假设您希望在客户端发生这种情况,那么可以使用A-如果您想在服务器端实现这一点,可以创建一个.< /P> 通过实现
IClientMessageInspector
可以在中检查结果,如果需要重试,则可以启动重试。。。当来电返回时,您只需“覆盖”使您使用新的。。。这样,操作调用方甚至不会注意到任何东西(除了调用有时需要更长的时间)

尽管在实现重试功能时必须小心(可能的重入问题需要适当处理)

有关一些示例代码(不包括重试本身),请参阅

编辑-根据评论:

如何实现重试操作取决于几个方面

基本上,您需要将调用与请求消息相关联,将请求消息与重播消息相关联

一种方法是实现OR,这将允许您记录调用参数的方法以及框架为其创建的消息对象

通过实现,您可以分配一个唯一的
correlationState
,这反过来允许您在的实现中关联回复消息,因为框架将使用它作为第二个参数调用您的实现

从那里,您可以使用反射重试调用(由于您在
IClientMessageFormatter
和/或
ipParameterInspector
实现中记录了类型、方法和参数,因此所有需要的信息都可用),并用新的应答覆盖应答消息

另一个(可能更简单)选项是实现一个自定义WCF客户机类,并向调用方提供该类。。。这使得你可以置身于各种各样的检查人员之外,并对任何被称为检查的操作进行更直接的控制

编辑2-根据评论:


在实现
IClientMessageInspector
时,还必须实现一个WCF运行时调用的方法,以添加
IClientMessageInspector
。在该方法中,实例化实现,该实现在构造函数中接受一个参数,而该参数又是or。您将此类型存储在inspector实例中。。。有关如何编写此代码的提示,请参见示例

我将使用unity接口/virtualmethod拦截

_unityContainer.AddNewExtension<Interception>(); 

_unityContainer.RegisterType<ITestCaching, TestCaching>(
    new Interceptor<InterfaceInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());

_unityContainer.RegisterType<XRepository>(
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());
该行为将在实现ICallHandler的类中实现

public class RetryCallHandler : ICallHandler, IDisposable
{

    public IMethodReturn Invoke(IMethodInvocation args, GetNextInterceptionBehaviorDelegate getNext) 
    { 
        Exception exception = null;
        int retryCounter = MAX_RETRIES;

        do
        {
            exception = null;
            try
            {
                var intercepted = getNext();
                IMethodReturn methodReturn = intercepted(args, getNext);

                return methodReturn;
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        }while(exception!=null && retryCounter-- > 0);


        return args.CreateExceptionMethodReturn(exception);
    }
}
我还没有编译或测试上述代码

我预见到的唯一问题是GetNextInterceptionBehaviorDelegate,以防出现多次拦截。
您可以管理呼叫处理程序的顺序,因此只需确保这是链中的最后一个。

不确定我是否理解您的意思。。。您希望在客户端的某个位置启动重试,但调用方没有注意到吗?@Yahia是的,我希望这在客户端发生。然后检查我答案中的链接。。。这应该能奏效…@SSamra我很好奇。如果你能添加一个答案,那就太棒了。@chibacity发布了我的答案,我刚刚将我的显示名称从“ssamra”改为“Surjit Samra”,谢谢你的回答,但WCF有内置的拦截功能,我想使用它。当然,如果这是一个完全痛苦的问题,我知道如何使用Ninject进行拦截:)我发现使用WCF内置设施很难做到这一点,但使用Castle DynamicProxy非常容易。使用WCF消息检查器等,您需要大量巫毒咒语和锅炉铭牌代码(没有找到好的文档);使用Castle Dynamic Proxy,您只需编写一个简单的拦截器加上两行代码即可生成代理。因此,如果您曾经需要执行类似的操作(我需要),我强烈建议您使用AOP/动态代理框架路线。那么,我将如何在接收后在
中实际重放调用呢?
?我可以看到您的回答如何允许我检查返回的消息,但我已经知道如何使用IParameterInspector执行此操作。如何重试该呼叫?@chibacity请参见上面我的编辑,以及“如何”的描述。。。虽然我建议为WCF客户机提供您自己的(扩展的)WCF客户机类,以避免麻烦…我知道我可以记录正在调用的操作,但如何准确地记录正在调用的类型,以便使用反射重播调用?
public class RetryCallHandler : ICallHandler, IDisposable
{

    public IMethodReturn Invoke(IMethodInvocation args, GetNextInterceptionBehaviorDelegate getNext) 
    { 
        Exception exception = null;
        int retryCounter = MAX_RETRIES;

        do
        {
            exception = null;
            try
            {
                var intercepted = getNext();
                IMethodReturn methodReturn = intercepted(args, getNext);

                return methodReturn;
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        }while(exception!=null && retryCounter-- > 0);


        return args.CreateExceptionMethodReturn(exception);
    }
}