惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog
C
Check Point Blog
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
SecWiki News
SecWiki News
有赞技术团队
有赞技术团队
Latest news
Latest news
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
Project Zero
Project Zero
H
Help Net Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
腾讯CDC
P
Proofpoint News Feed
L
LINUX DO - 热门话题
C
Cisco Blogs
P
Palo Alto Networks Blog
Vercel News
Vercel News
P
Privacy International News Feed
爱范儿
爱范儿
Scott Helme
Scott Helme
L
Lohrmann on Cybersecurity
MyScale Blog
MyScale Blog
K
Kaspersky official blog
B
Blog RSS Feed
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
O
OpenAI News
博客园 - 叶小钗
量子位
T
Tenable Blog
C
Cybersecurity and Infrastructure Security Agency CISA
J
Java Code Geeks
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LINUX DO - 最新话题
F
Fortinet All Blogs
N
News | PayPal Newsroom
The Hacker News
The Hacker News
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 【当耐特】
N
News and Events Feed by Topic
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI

博客园 - JerryShi

使用流模式传输大型数据 对象序列化之 替换(Surrogate) 使用 IExtensibleDataObject 进行往返式序列化 使用 NetDataContractSerializer 共享类型 WCF可序列化方式 序列化 VS 编码 操作行为 之 事务 服务行为 之 元数据 服务行为 之 并发与实例化 基本的WCF编程(实例) WCF Behaviors(行为) WCF 体系结构 WCF服务 使用netTcpBinding 无法打开默认数据库 SharePoint 创建SSP时出现找不到 Windows NT 用户或组 的异常 SQL Server 2008 Mirror 泛型(一) 自定义属性Attribute(三) 自定义属性Attribute(二)
自定义 Behavior
JerryShi · 2011-10-21 · via 博客园 - JerryShi

自定义Behavior 允许在WCF 构建运行时环境和消息处理管道的关键点上插入代码。

实现自定义行为的步骤:

1. 创建一个实现了 Inspector、Selector、Formatter、或Invoker 接口的类;

2. 创建一个实现了下列行为接口之一的类:IServiceBehavior、IEndpointBehavior、IOperationBehavior或IContractBehavior;

3. 配置客户端或服务来使用行为,可由 代码、配置文件、属性来完成;

服务端行为实现消息检验器

该Demo实现一个日志行为,输出端点发送和接收的每条消息,代码实现了从端点行为调用的一个消息检验器,以及在一个自定义扩管服务中手工的向服务描述添加端点行为。

public class MyEndpointBehavior : IEndpointBehavior
    {
        #region IEndpointBehavior Members

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyMessageInspector());
        }

        public void Validate(ServiceEndpoint endpoint)
        {
            
        }

        #endregion
    }

    public class MyMessageInspector : IDispatchMessageInspector
    {

        #region IDispatchMessageInspector Members

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            Console.WriteLine(request.ToString());
            return request;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            
        }

        #endregion
    }

执行结果:

结果

结果分析:

服务端输出每次接收到的Message数据;

通过属性暴露服务操作行为的参数检验器

Demo功能说明: 使用正则表达式对参数进行校验,当参数无效时返回错误消息; 从操作行为调用参数检验器,实现属性的操作行为,在服务定义中通过属性引用将操作行为添加到服务描述中;

[AttributeUsage(AttributeTargets.Method)]
    public class MyOperationBehavior : Attribute, IOperationBehavior
    {
        public string Pattern;
        public string Message;

        #region IOperationBehavior Members

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.ParameterInspectors.Add(new MyParameterInspector(Pattern, Message));
        }

        public void Validate(OperationDescription operationDescription)
        {
            
        }

        #endregion
    }

    public class MyParameterInspector : IParameterInspector
    {
        string pattern;
        string message;

        public MyParameterInspector(string pattern, string message)
        {
            this.pattern = pattern;
            this.message = message;
        }

        #region IParameterInspector Members

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
            
        }

        public object BeforeCall(string operationName, object[] inputs)
        {
            foreach (object input in inputs)
            {
                if (input != null && input.GetType().Equals(typeof(string)))
                {
                    Regex regex = new Regex(pattern);
                    if (regex.IsMatch(input.ToString()))
                    {
                        throw new FaultException(string.Format("Parameter out of range : {0} , {1}", input.ToString(), message));
                    }
                }
            }
            return null;
        }

        #endregion
    }
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class StockService : IStockService
    {        
        public StockService()
        {
            Console.WriteLine("{0}:Created new instance of StockService on thread", DateTime.Now);
        }

        public class Worker
        {
            public string ticker;
            public Update workProcess;
        }

        public static Hashtable workers = new Hashtable();
        public static object locker = new object();
        private int callsCounter = 0;

        #region IStockService Members

        [MyOperationBehavior(Pattern="[^a-zA-Z]",Message="Only alpha characters allowed")]
        public double GetPrice(string ticker)
        {
            Console.WriteLine("{0}: GetPrice called on thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);            
            Thread.Sleep(5000);
            return 94.85;
        }

        public void RegisterForUpdate(string ticker)
        {
            Worker worker = null;

            if (!workers.ContainsKey(ticker))
            {
                worker = new Worker();
                worker.ticker = ticker;
                worker.workProcess = new Update();
                worker.workProcess.ticker = ticker;
                workers.Add(ticker, worker);
            }

            worker = (Worker)workers[ticker];
            IStockServiceCallback c = OperationContext.Current.GetCallbackChannel(); lock (worker.workProcess.callbacks) { worker.workProcess.callbacks.Add(c); } Thread t = new Thread(new ThreadStart(worker.workProcess.SendUpdateToClient)); t.IsBackground = true; t.Start(); } public StockPrice GetStockPrice(string ticker) { StockPrice p = new StockPrice(); Console.WriteLine("{0}: GetPrice called on thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId); p.Price = 94.85; lock (locker) { p.CallsCounter = ++callsCounter; } Thread.Sleep(1000); return p; } #endregion } public class Update { public string ticker; public List callbacks = new List(); public void SendUpdateToClient() { Random w = new Random(); Random p = new Random(); for (int i = 0; i < 10; i++) { Thread.Sleep(w.Next(5000)); lock (callbacks) { foreach (IStockServiceCallback callback in callbacks) { try { callback.PriceUpdate("msft", 100.00 + p.NextDouble()); } catch (Exception ex) { Console.WriteLine("Error sending cache to client:{0}", ex.Message); } } } } } }

执行结果

调试状态下直接报出错误信息

通过配置文件暴露服务行为

实现IServiceBehavior,代码:

public class MyServiceBehavior : IServiceBehavior
    {
        string evaluationKey;
        string evaluationType;

        public MyServiceBehavior(string evaluationKey, string evaluationType)
        {
            this.evaluationKey = evaluationKey;
            this.evaluationType = evaluationType;
        }

        #region IServiceBehavior Members

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { if (evaluationType.Equals("Enterprise", StringComparison.OrdinalIgnoreCase) & !evaluationKey.Equals("SuperSecretEvaluationKey", StringComparison.OrdinalIgnoreCase)) { throw new Exception(string.Format("Invalid evaluation key. Type:{0}", evaluationType)); } } #endregion }

配置: