天天看点

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

在上一篇文章中,我们讨论了如何通过CallContextInitializer实现Localization的例子,具体的做法是将client端的culture通过SOAP header传到service端,然后通过自定义的CallContextInitializer设置当前方法执行的线程culture。在client端,当前culture信息是通过OperationContext.Current.OutgoingMessageHeaders手工至于SOAP Header中的。实际上,我们可以通过基于WCF的另一个可扩展对象来实现这段逻辑,这个可扩展对象就是MessageInspector。我们今天来讨论MessageInspector应用的另外一个场景:如何通过MessageInspector来传递Context信息。

1. Ambient Context

在一个多层结构的应用中,我们需要传递一些上下文的信息在各层之间传递,比如:为了进行Audit,需要传递一些当前当前user profile的一些信息。在一些分布式的环境中也可能遇到context信息从client到server的传递。如何实现这种形式的Context信息的传递呢?我们有两种方案:

一、将Context作为参数传递:将context作为API的一部分,context的提供者在调用context接收者的API的时候显式地设置这些Context信息,context的接收者则直接通过参数将context取出。这虽然能够解决问题,但决不是一个好的解决方案,因为API应该只和具体的业务逻辑有关,而context 一般是与非业务逻辑服务的,比如Audit、Logging等等。此外,将context纳入API作为其一部分,将降低API的稳定性, 比如,今天只需要当前user所在组织的信息,明天可能需求获取当前客户端的IP地址,你的API可以会经常变动,这显然是不允许的。

二、创建Ambient Context来保存这些context信息,Ambient Context可以在不同的层次之间、甚至是分布式环境中每个节点之间共享或者传递。比如在ASP.NET 应用中,我们通过SessionSate来存储当前Session的信息;通过HttpContext来存储当前Http request的信息。在非Web应用中,我们通过CallContext将context信息存储在TLS(Thread Local Storage)中,当前线程下执行的所有代码都可以访问并设置这些context数据。

2、Application Context

介于上面所述,我创建一个名为Application Context的Ambient Context容器,Application Context实际上是一个dictionary对象,通过key-value pair进行context元素的设置,通过key获取相对应的context元素。Application Context通过CallContext实现,定义很简单:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    [Serializable]

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class ApplicationContext:Dictionary<string,object>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        private const string CallContextKey = "__ApplicationContext";    

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        internal const string ContextHeaderLocalName = "__ApplicationContext";

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        internal const string ContextHeaderNamespace = "urn:artech.com"; 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        private void EnsureSerializable(object value)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (value == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                throw new ArgumentNullException("value");

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (!value.GetType().IsSerializable)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                throw new ArgumentException(string.Format("The argument of the type /"

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{0}/" is not serializable!", value.GetType().FullName));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        }       

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public new  object this[string key]

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return base[key];

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            set

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                this.EnsureSerializable(value);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                base[key] = value;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public int Counter

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

               return (int)this["__Count"];

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            set

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                this["__Count"] = value;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public static ApplicationContext Current

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                if (CallContext.GetData(CallContextKey) == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                    CallContext.SetData(CallContextKey, new ApplicationContext());

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return CallContext.GetData(CallContextKey) as ApplicationContext;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            set

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                CallContext.SetData(CallContextKey, value);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        }     

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

由于此Context将会置于SOAP Header中从client端向service端进行传递,我们需要为此message header指定一个local name和namespace,那么在service端,才能通过此local name和namespace获得此message header。同时,在lcoal domain, client或者service,context是通过CallContext进行存取的,CallContext也是一个类似于disctionary的结构,也需要为此定义一个Key:

private const string CallContextKey = "__ApplicationContext"; internal const string ContextHeaderLocalName = "__ApplicationContext";

internal const string ContextHeaderNamespace = "urn:artech.com";

由于ApplicaitonContext直接继承自Dictionary<string,object>,我们可以通过Index进行元素的设置和提取,考虑到context的跨域传播,需要进行序列化,所以重写了Indexer,并添加了可序列化的验证。为了后面演示方面,我们定义一个context item:Counter。

Static类型的Current属性通过CallContext的SetData和GetData方法对当前的ApplicationContext进行设置和提取:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

public static ApplicationContext Current

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                if (CallContext.GetData(CallContextKey) == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                    CallContext.SetData(CallContextKey, new ApplicationContext());

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return CallContext.GetData(CallContextKey) as ApplicationContext;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            set

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                CallContext.SetData(CallContextKey, value);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

}     

3、通过MessageInspector将AppContext置于SOAP header中

通过本系列第3部分对Dispatching system的介绍了,我们知道了在client端和service端,可以通过MessageInspector对request message或者reply message (incoming message或者outgoings message)进行检验。MessageInspector可以对MessageHeader进行自由的添加、修改和删除。在service端的MessageInspector被称为DispatchMessageInspector,相对地,client端被称为ClientMessageInspector。我们现在自定义我们自己的ClientMessageInspector。

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class ContextAttachingMessageInspector:IClientMessageInspector

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public bool IsBidirectional

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ get; set; } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextAttachingMessageInspector()

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            : this(false)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextAttachingMessageInspector(bool isBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            this.IsBidirectional = IsBidirectional;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        IClientMessageInspector Members#region IClientMessageInspector Members 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void AfterReceiveReply(ref Message reply, object correlationState)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (IsBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (reply.Headers.FindHeader(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace) < 0)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext context = reply.Headers.GetHeader<ApplicationContext>(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (context == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext.Current = context;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public object BeforeSendRequest(ref Message request, IClientChannel channel)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            MessageHeader<ApplicationContext> contextHeader = new MessageHeader<ApplicationContext>(ApplicationContext.Current);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            request.Headers.Add(contextHeader.GetUntypedHeader(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return null;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        #endregion

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

一般地,我们仅仅需要Context的单向传递,也就是从client端向service端传递,而不需要从service端向client端传递。不过回来应付将来潜在的需求,也许可能需要这样的功能:context从client端传向service端,service对其进行修改后需要将其返回到client端。为此,我们家了一个属性:IsBidirectional表明是否支持双向传递。

在BeforeSendRequest,我们将ApplicationContext.Current封装成一个MessageHeader, 并将此MessageHeader添加到request message 的header集合中,local name和namespace采用的是定义在ApplicationContext中常量:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

public object BeforeSendRequest(ref Message request, IClientChannel channel)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            MessageHeader<ApplicationContext> contextHeader = new MessageHeader<ApplicationContext>(ApplicationContext.Current);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            request.Headers.Add(contextHeader.GetUntypedHeader(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return null;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

如何支持context的双向传递,我们在AfterReceiveReply负责从reply message中接收从service传回的context,并将其设置成当前的context:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

public   void  AfterReceiveReply( ref  Message reply,  object  correlationState)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        if (IsBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        if (reply.Headers.FindHeader(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace) < 0)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

             return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        ApplicationContext context = reply.Headers.GetHeader<ApplicationContext>(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        if (context == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        ApplicationContext.Current = context;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

}  

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

4、通过ContextInitializer实现对Context的接收

上面我们介绍了在client端通过ClientMessageInspector将context信息存储到request message header中,照理说我们通过可以通过DispatchMessageInspector实现对context信息的提取,但是考虑到我们设置context是通过CallContext来实现了,我们最好还是使用CallContextInitializer来做比较好一些。CallContextInitializer的定义,我们在上面一章已经作了详细的介绍了,在这里就不用多说什么了。

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class ContextReceivalCallContextInitializer : ICallContextInitializer

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public bool IsBidirectional

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ get; set; } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextReceivalCallContextInitializer()

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            : this(false)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextReceivalCallContextInitializer(bool isBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            this.IsBidirectional = isBidirectional;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        ICallContextInitializer Members#region ICallContextInitializer Members 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void AfterInvoke(object correlationState)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (!this.IsBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext context = correlationState as ApplicationContext;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (context == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            MessageHeader<ApplicationContext> contextHeader = new MessageHeader<ApplicationContext>(context);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            OperationContext.Current.OutgoingMessageHeaders.Add(contextHeader.GetUntypedHeader(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext.Current = null;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext context = message.Headers.GetHeader<ApplicationContext>(ApplicationContext.ContextHeaderLocalName, ApplicationContext.ContextHeaderNamespace);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            if (context == null)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return null;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext.Current = context;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return ApplicationContext.Current;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        #endregion

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

代码其实很简单,BeforeInvoke中通过local name和namespace提取context对应的message header,并设置当前的ApplicationContext。如果需要双向传递,则通过AfterInvoke方法将context保存到reply message的header中被送回client端。

5. 为MessageInspector和CallContextInitializer创建behavior:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class ContextPropagationBehavior: IEndpointBehavior

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public bool IsBidirectional

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ get; set; } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextPropagationBehavior()

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            : this(false)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{ } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public ContextPropagationBehavior(bool isBidirectional)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            this.IsBidirectional = isBidirectional;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        IEndpointBehavior Members#region IEndpointBehavior Members 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            clientRuntime.MessageInspectors.Add(new ContextAttachingMessageInspector(this.IsBidirectional));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                operation.CallContextInitializers.Add(new ContextReceivalCallContextInitializer(this.IsBidirectional));

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void Validate(ServiceEndpoint endpoint)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        #endregion

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

在ApplyClientBehavior中,创建我们的ContextAttachingMessageInspector对象,并将其放置到ClientRuntime 的MessageInspectors集合中;在ApplyDispatchBehavior,将ContextReceivalCallContextInitializer对象放到每个DispatchOperation的CallContextInitializers集合中。

因为我们需要通过配置的方式来使用我们的ContextPropagationBehavior,我们还需要定义对应的BehaviorExtensionElement:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class ContextPropagationBehaviorElement:BehaviorExtensionElement

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        [ConfigurationProperty("isBidirectional", DefaultValue = false)]

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public bool IsBidirectional

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return (bool)this["isBidirectional"];

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            set

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                this["isBidirectional"] = value;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public override Type BehaviorType

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            get 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                return typeof(ContextPropagationBehavior); 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        protected override object CreateBehavior()

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            return new ContextPropagationBehavior(this.IsBidirectional);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

我们IsBidirectional则可以通过配置的方式来指定。

6. Context Propagation的运用

我们现在将上面创建的对象应用到真正的WCF调用环境中。我们依然创建我们经典的4层结构:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
  • Artech.ContextPropagation.Contract:
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace  Artech.ContextPropagation.Contract

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    [ServiceContract]

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public interface IContract

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        [OperationContract]

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        void DoSomething();

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

}  

  • Artech.ContextPropagation.Services
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation.Services

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    public class Service:IContract

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        IContract Members#region IContract Members

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        public void DoSomething()

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            Console.WriteLine("ApplicationContext.Current.Count = {0}", ApplicationContext.Current.Counter);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            ApplicationContext.Current.Counter++;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        } 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        #endregion

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

打印出ApplicationContext.Current.Count 的值,并加1。

  • Hosting的Config:
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

<configuration>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    <system.serviceModel>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <behaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <endpointBehaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                <behavior name="contextPropagationBehavior">

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                    <contextPropagationElement isBidirectional="true" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                </behavior>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            </endpointBehaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </behaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <client>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <endpoint address="http://127.0.0.1/service" behaviorConfiguration="contextPropagationBehavior"

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                binding="basicHttpBinding" contract="Artech.ContextPropagation.Contract.IContract"

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                name="service" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </client>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <extensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <behaviorExtensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                <add name="contextPropagationElement" type="Artech.ContextPropagation.ContextPropagationBehaviorElement, Artech.ContextPropagation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            </behaviorExtensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </extensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    </system.serviceModel>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

</configuration>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

Artech.ContextPropagation.Client

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

namespace Artech.ContextPropagation.Client

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    class Program

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        static void Main(string[] args)

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            using (ChannelFactory<IContract> channelFactory = new ChannelFactory<IContract>("service"))

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

{

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                IContract proxy = channelFactory.CreateChannel();

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                ApplicationContext.Current.Counter = 100;

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                Console.WriteLine("Brfore service invocation: ApplicationContext.Current.Count = {0}", ApplicationContext.Current.Counter);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                proxy.DoSomething();

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                Console.WriteLine("After service invocation: ApplicationContext.Current.Count = {0}", ApplicationContext.Current.Counter);

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                Console.Read();

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    }

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

以及config:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

<configuration>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    <system.serviceModel>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <behaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <endpointBehaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

               <behavior name="contextPropagationBehavior">

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                    <contextPropagationElement isBidirectional="true" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                </behavior>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            </endpointBehaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </behaviors>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <client>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <endpoint address="http://127.0.0.1/service" behaviorConfiguration="contextPropagationBehavior"

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                binding="basicHttpBinding" contract="Artech.ContextPropagation.Contract.IContract"

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                name="service" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </client>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        <extensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            <behaviorExtensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

                <add name="contextPropagationElement" type="Artech.ContextPropagation.ContextPropagationBehaviorElement, Artech.ContextPropagation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

            </behaviorExtensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

        </extensions>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

    </system.serviceModel>

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

</configuration> 

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

我们运行整个程序,你将会看到如下的输出结果:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

可见,Context被成功传播到service端。再看看client端的输出:

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

由此可见,在service端设置的context的值也成功返回到client端,真正实现了双向传递。

P.S: SOA主张Stateless的service,也就是说每次调用service都应该是相互独立的。context的传递实际上却是让每次访问有了状态,这实际上是违背了SOA的原则。所以,如何对于真正的SOA的设计与架构,个人觉得这种方式是不值得推荐的。但是,如何你仅仅是将WCF作为传统的分布式手段,那么这可能会给你的应用带了很大的便利。

WCF后续之旅:

[原创]WCF后续之旅(1): WCF是如何通过Binding进行通信的

[原创]WCF后续之旅(2): 如何对Channel Layer进行扩展——创建自定义Channel

[原创]WCF后续之旅(3): WCF Service Mode Layer 的中枢—Dispatcher

[原创]WCF后续之旅(4):WCF Extension Point 概览

[原创]WCF后续之旅(5): 通过WCF Extension实现Localization

[原创]WCF后续之旅(6): 通过WCF Extension实现Context信息的传递

[原创]WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成

[原创]WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成

[原创]WCF后续之旅(9):通过WCF的双向通信实现Session管理[Part I]

[原创]WCF后续之旅(9): 通过WCF双向通信实现Session管理[Part II]

[原创]WCF后续之旅(10): 通过WCF Extension实现以对象池的方式创建Service Instance

我的WCF之旅:

[原创]我的WCF之旅(1):创建一个简单的WCF程序

[原创]我的WCF之旅(2):Endpoint Overview

[原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication)

[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part I

[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part II

[原创]我的WCF之旅(5):Service Contract中的重载(Overloading)

[原创]我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案

[原创]我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承

[原创]我的WCF之旅(8):WCF中的Session和Instancing Management

[原创]我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace

[原创]我的WCF之旅(10): 如何在WCF进行Exception Handling

[原创]我的WCF之旅(11):再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

[原创]我的WCF之旅(12):使用MSMQ进行Reliable Messaging

[原创]我的WCF之旅(13):创建基于MSMQ的Responsive Service

继续阅读