CLR中IMessageSink IContextProperty与Attribute等等

来源:互联网 发布:erp主生产计划算法 编辑:程序博客网 时间:2024/05/17 04:28

Essential.net 书到了第七章部分介绍到IMessageSink的时候就从简了,但这个也是第七章乃至整本书乃至

CLR本身最难理解的部分之一,因为要在ContextboundObject中无缝的添加自定义属性涉及到几个类的合作,比较的麻烦。

但是不了解始终不爽,于是本人就实现了第七章关于扩展IContributeEnvoySink,IContributeServerContextSink应用的那部分代码以使得其完整可运行。

///具体使用上述属性的例子ContextBound的子类
 ///这个例子比上一个MyCalcXX更加充分的使用了上下文特性,使用了两个实现的sink一个在客户端一个在服务器端
 ///而不是用了简单的proxyAttribute。在ContextboundObject的时候就没有比较原始的外加Invoke实现的rp了,而是
 ///全部通过自定义的上下文属性来增加从代理到上下文绑定对象之间的消息接收器的使用,而作为过渡的版本proxyAttribute
 ///还是提供了让用户程序员设置rp的invoke来传递信息的能力,而无论如何最强大的还是通过Property挂上sink的链式调用
 ///对于ContextboundObject对象使用消息机制的标准方法是
 ///1实现 自定义的各个阶段的sink,完成各种传输功能
 ///2实现 上下文property,并且通过接口包含1里实现的sink
 ///3实现 特定的attribute来包装以及实例化2里的property
 ///4将attribute声明到到指定的ContextboundObject前
 ///  
 /// 
 /// 这样的话,在使用ContextboundObject对象的时候就没有与实际引用的区别,甚至引用是跨越物理边界的也可以
 /// 不过ContextboundObject对象的透明代理在一开始引用上具体对象的时候,跨不跨CLR还是有点区别的,本地通过new
 /// 指令的话,本地CLR的干活实例化一个对象,如果是uri的话IMessage通过了CrossContextChannel这个sink之后就
 /// 出了本地物理界限了,剩下的事情是在别的物理环境里面的服务器sink的事情,CLR对于IMessage从哪个sink来到哪个sink去是知道的
 /// 否则也无法回调上下文Property里的IMessage了

以下是完整的代码:

using System;

namespace Chapter7
{
 ///客户与服务器sink是一对一的,在crosschannel的时候需要这样以调整上下文

 ///跨线程传播上下文
 internal class EnvoyData: System.Runtime.Remoting.Messaging.ILogicalThreadAffinative
 {
  internal System.Threading.ThreadPriority clientPriority;
  internal EnvoyData(System.Threading.ThreadPriority level)
  {
   clientPriority = level;
  }
 }

 
 ///转发sink作为客户端
 ///
 public class PriorityEnvoySink : System.Runtime.Remoting.Messaging.IMessageSink
 {
  internal System.Runtime.Remoting.Messaging.IMessageSink next;

  public PriorityEnvoySink(System.Runtime.Remoting.Messaging.IMessageSink next)
  {
   this.next = next;
  }

  #region IMessageSink 成员

  public System.Runtime.Remoting.Messaging.IMessage SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage m)
  {
   // TODO:  添加 PriorityEnvoySink.SyncProcessMessage 实现
   System.Runtime.Remoting.Messaging.IMethodCallMessage call = (System.Runtime.Remoting.Messaging.IMethodCallMessage)m;
   call.LogicalCallContext.SetData("clientPriority",new EnvoyData(System.Threading.Thread.CurrentThread.Priority));
   ///察看过程
   System.Console.WriteLine("New Priority has just been set");
   return next.SyncProcessMessage(call);
  }

  public System.Runtime.Remoting.Messaging.IMessageSink NextSink
  {
   get
   {
    // TODO:  添加 PriorityEnvoySink.NextSink getter 实现
    return this.next;
   }
  }

  public System.Runtime.Remoting.Messaging.IMessageCtrl AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Messaging.IMessageSink replySink)
  {
   // TODO:  添加 PriorityEnvoySink.AsyncProcessMessage 实现
   return null;
  }

  #endregion

 }


 ///服务器端sink
 ///
 public class PriorityServerSink : System.Runtime.Remoting.Messaging.IMessageSink
 {
  internal System.Runtime.Remoting.Messaging.IMessageSink next;

  public PriorityServerSink(System.Runtime.Remoting.Messaging.IMessageSink next)
  {
   this.next = next;
  }

  #region IMessageSink 成员

  /// <summary>
  /// 实际上不再转发了
  /// </summary>
  /// <param name="msg"></param>
  /// <returns></returns>
  public System.Runtime.Remoting.Messaging.IMessage SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage m)
  {
   // TODO:  添加 PriorityServerSink.SyncProcessMessage 实现
   System.Runtime.Remoting.Messaging.IMethodCallMessage call = (System.Runtime.Remoting.Messaging.IMethodCallMessage)m;
   System.Runtime.Remoting.Messaging.LogicalCallContext cc = call.LogicalCallContext;
   Chapter7.EnvoyData ed = (Chapter7.EnvoyData)cc.GetData("clientPriority");

   ///进行boost-dispatch-unboost
   ///
   System.Threading.Thread here = System.Threading.Thread.CurrentThread;
   System.Threading.ThreadPriority old = here.Priority;
   if(ed.clientPriority != System.Threading.ThreadPriority.Highest)
   {
    here.Priority = ed.clientPriority + 1;
   }
   ///察看过程
   System.Console.WriteLine("New Priority has just been read");
   System.Runtime.Remoting.Messaging.IMessage response = next.SyncProcessMessage(call);
   if(ed.clientPriority != System.Threading.ThreadPriority.Highest)
   {
    here.Priority = old;
   }
   return response;
  }

  public System.Runtime.Remoting.Messaging.IMessageSink NextSink
  {
   get
   {
    // TODO:  添加 PriorityServerSink.NextSink getter 实现
    return next;
   }
  }

  public System.Runtime.Remoting.Messaging.IMessageCtrl AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Messaging.IMessageSink replySink)
  {
   // TODO:  添加 PriorityServerSink.AsyncProcessMessage 实现
   return null;
  }

  #endregion

 }

 
 
 
 
 ///上下文属性插入以上两个sink
 ///
 public class BoostProperty: System.Runtime.Remoting.Contexts.IContextProperty,
  System.Runtime.Remoting.Contexts.IContributeEnvoySink,
  System.Runtime.Remoting.Contexts.IContributeServerContextSink 
 {
  #region IContextProperty 成员

  public string Name
  {
   get
   {
    // TODO:  添加 BoostProperty.Name getter 实现
    ///作为本属性的名字
    return "Boost";
   }
  }

  public bool IsNewContextOK(System.Runtime.Remoting.Contexts.Context newCtx)
  {
   // TODO:  添加 BoostProperty.IsNewContextOK 实现
   return true;
  }

  public void Freeze(System.Runtime.Remoting.Contexts.Context newContext)
  {
   // TODO:  添加 BoostProperty.Freeze 实现
  }

  #endregion

  #region IContributeEnvoySink 成员

  /// <summary>
  /// IContributeEnvoySink还是可以有obj传过来的,因为在客户端
  /// </summary>
  /// <param name="obj"></param>
  /// <param name="n"></param>
  /// <returns></returns>
  public System.Runtime.Remoting.Messaging.IMessageSink GetEnvoySink(MarshalByRefObject obj, System.Runtime.Remoting.Messaging.IMessageSink next)
  {
   // TODO:  添加 BoostProperty.GetEnvoySink 实现
   return new Chapter7.PriorityEnvoySink(next);
  }

  #endregion

  #region IContributeServerContextSink 成员

  /// <summary>
  /// 但是作为服务端的sink就没有了
  /// </summary>
  /// <param name="next"></param>
  /// <returns></returns>
  public System.Runtime.Remoting.Messaging.IMessageSink GetServerContextSink(System.Runtime.Remoting.Messaging.IMessageSink next)
  {
   // TODO:  添加 BoostProperty.GetServerContextSink 实现
   return new Chapter7.PriorityServerSink(next);
  }

  #endregion
 }


 ///attribute使用上下文属性
 ///
 [System.AttributeUsageAttribute(System.AttributeTargets.Class)]
 public class BoostPropertyAttribute : System.Attribute, System.Runtime.Remoting.Contexts.IContextAttribute
 {
  #region IContextAttribute 成员

  public void GetPropertiesForNewContext(System.Runtime.Remoting.Activation.IConstructionCallMessage ctor)
  {
   // TODO:  添加 BoostPropertyAttribute.GetPropertiesForNewContext 实现
   
   ///在构造函数执行的时候插入特定的上下文属性给server因为此时envoy还得不到信息
   ctor.ContextProperties.Add(new Chapter7.BoostProperty());
   ctor.LogicalCallContext.SetData("clientPriority",new EnvoyData(System.Threading.Thread.CurrentThread.Priority));
  }

  /// <summary>
  /// 调度EnvoySink和ServerSink需要显示的来作的待定
  /// </summary>
  /// <param name="ctx"></param>
  /// <param name="msg"></param>
  /// <returns></returns>
  public bool IsContextOK(System.Runtime.Remoting.Contexts.Context current, System.Runtime.Remoting.Activation.IConstructionCallMessage msg)
  {
   // TODO:  添加 BoostPropertyAttribute.IsContextOK 实现

   ///为以上定义的Property名字
   return (System.Object)current.GetProperty("Boost") != null;
  }

  #endregion

 }


 ///具体使用上述属性的例子ContextBound的子类
 ///这个例子比上一个MyCalcXX更加充分的使用了上下文特性,使用了两个实现的sink一个在客户端一个在服务器端
 ///而不是用了简单的proxyAttribute。在ContextboundObject的时候就没有比较原始的外加Invoke实现的rp了,而是
 ///全部通过自定义的上下文属性来增加从代理到上下文绑定对象之间的消息接收器的使用,而作为过渡的版本proxyAttribute
 ///还是提供了让用户程序员设置rp的invoke来传递信息的能力,而无论如何最强大的还是通过Property挂上sink的链式调用
 ///对于ContextboundObject对象使用消息机制的标准方法是
 ///1实现 自定义的各个阶段的sink,完成各种传输功能
 ///2实现 上下文property,并且通过接口包含1里实现的sink
 ///3实现 特定的attribute来包装以及实例化2里的property
 ///4将attribute声明到到指定的ContextboundObject前
 ///  
 /// 
 /// 这样的话,在使用ContextboundObject对象的时候就没有与实际引用的区别,甚至引用是跨越物理边界的也可以
 /// 不过ContextboundObject对象的透明代理在一开始引用上具体对象的时候,跨不跨CLR还是有点区别的,本地通过new
 /// 指令的话,本地CLR的干活实例化一个对象,如果是uri的话IMessage通过了CrossContextChannel这个sink之后就
 /// 出了本地物理界限了,剩下的事情是在别的物理环境里面的服务器sink的事情,CLR对于IMessage从哪个sink来到哪个sink去是知道的
 /// 否则也无法回调上下文Property里的IMessage了
 /// 
 /// 
 ///   
 [Chapter7.BoostProperty()]
 public class MyCalcXXX : System.ContextBoundObject,Chapter7.ICalculator
 {
  #region ICalculator 成员

  public int Add(int x, int y)
  {
   // TODO:  添加 MyCalcXX.Add 实现

    return x+y;
  }

  public int Multiply(int x, int y)
  {
   // TODO:  添加 MyCalcXX.Multiply 实现
   return 0;
  }

  #endregion

 }
}

 

原创粉丝点击