我所理解的Remoting(3):创建CAO Service Factory使接口和实现相互分离
ICounter counter = ICounterFactory counterFactory = (ICounterFactory)Activator.GetObject(typeof(ICounterFactory), remoteAddress);
对于Client Activation,由于我们在创建Proxy对象的时候,必须利用远程对象对应的原数据,所以在Client端,需要引用远程的对象所对应的dll。比如我们现在做一个简单的计数器的例子(Client远程调用获得计数器当前的计数)我们把业务逻辑封装在Counter Service的实体中。下图反映了这样一种架构的依赖关系。
经验丰富的开发人员很快会意识到这是一种很不好的分布式构架。从SOA的角度来讲也是不值得推荐的构架方式。SOA崇尚的是Contract层面的共享,而拒绝Type层面的共享。Common Type增加了交互双方的依赖性,造成的紧耦合。所以我们一般从Service中把相对静态的Contract(可以简单地把 Contract看成是Service提供的所有操作的列表和调用的接口)提取出来,作为双方交互的契约:Client只要满足这个Contract,它就能够调用相应的Service,而Service 真正实现的改变对Client没有任何的影响,实际上Service的实现对于Client来说是完全透明的。我们可以说基于Contract的共享成就了SOA的松耦合。通过提取Contract之后,各个实体成为了下面一种依赖关系。
但是对于Client Activation,要直接实现这样的构架是不可能的。我们已经说过,Client创建一个CAO Proxy,需要和Host端注册的远程类型对应的原数据,换句话说,如果远程类型实现在CounterService的dll中,Host和Client双方都需要引用这个dll——虽然实现部分的代码对Client毫无意义。但是现在我们的目的的吧这个dll仅仅驻留在Host中,Client只需引用存储Contract的dll。
在一个分布式环境中,一个Application要跨AppDomain调用一个驻留在另一个AppDomain的的方法,他不需要获得这个真正的远程对象(而实事上它也不可能获得在另一个AppDomain中创建的对象),它只需要获得该对象的一个引用(说得具体点,它只需要获得该对象的ObjRef),并根据这个引用创建相应的Proxy来进行远程调用。或者说,我们只要通过某种方法把Server端创建的对象通过Marshaling传递到Client端,Client就可以进行远程调用了。
那么如何为一个远程调用从另一个AppDomain中获取一个远程对象的引用并创建Proxy呢?而这个获取的方式本身也是一个远程调用。我们的做法是:通过一个基于SAO的远程调用获取一个远程对象的引用并同时创建Proxy。而这个Proxy对应的远程对象就像当于一个CAO.
下面是我们的解决方案简要的类图。我们整个基于计数器的Service封装在CounterService中,它实现了ICounter接口,CounterFactoryService用于创建一个CounterService对象,它实现的接口是ICounterFactory。
现在我们就来实现它:
Step 1: 建立这个Solution的整体结构
整个Solution包含3个Project:Artech.CAOFactory.Contract;Artech.CAOFactory.Service;Artech.CAOFactory.Client。Artech.CAOFactory.Contract被Artech.CAOFactory.Service和Artech.CAOFactory.Client引用。我们使用IIS的Host方式,从而省略了Host Application。
Step 2 创建Contract
ICounter
using System.Collections.Generic;
using System.Text;
namespace Artech.CAOFactory.Contract
{
public interface ICounter
{
int GetCount();
}
}
ICounterFactory
using System.Collections.Generic;
using System.Text;
namespace Artech.CAOFactory.Contract
{
public interface ICounterFactory
{
ICounter CreateService();
}
}
Step 3 实现Contract:Artech.CAOFactory.Service
using System.Collections.Generic;
using System.Text;
using Artech.CAOFactory.Contract;
namespace Artech.CAOFactory.Service
{
public class CounterService : MarshalByRefObject,ICounter
{
private int _count;
ICounter Members
}
}
CounterFactoryService
using System.Collections.Generic;
using System.Text;
using Artech.CAOFactory.Contract;
namespace Artech.CAOFactory.Service
{
public class CounterFactoryService :MarshalByRefObject, ICounterFactory
{
ICounterFactory Members
}
}
Step 3 通过IIS Host CounterFactoryService
修改编译配置把Dll生成在Project根目录的bin目录下,基于这个根目录创建虚拟目录(假设Alias就是Artech.CAOFactory),并添加Web.config。
<configuration>
<configSections>
<section name="WorkflowRuntime" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<WorkflowRuntime Name="WorkflowServiceContainer">
<Services>
<add type="System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add type="System.Workflow.Runtime.Hosting.DefaultWorkflowCommitWorkBatchService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</Services>
</WorkflowRuntime>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="false"/>
<authentication mode="Windows"/>
</system.web>
<system.runtime.remoting>
<application>
<service>
<wellknown type="Artech.CAOFactory.Service.CounterFactoryService, Artech.CAOFactory.Service"
mode ="SingleCall" objectUri="CounterFactory.rem"></wellknown>
</service>
</application>
</system.runtime.remoting>
</configuration>
Step 4 创建客户端Artech.CAOFactory.Client
Program
using System.Collections.Generic;
using System.Text;
using Artech.CAOFactory.Contract;
using System.Threading;
using System.Runtime.Remoting;
namespace Artech.CAOFactory.Client
{
class Program
{
const string REMOTE_ADDRESS = "http://localhost/Artech.CAOFactory/CounterFactory.rem";
static void Main(string[] args)
{
ICounterFactory counterFactory = (ICounterFactory)Activator.GetObject(typeof(ICounterFactory), REMOTE_ADDRESS);
ICounter counter = counterFactory.CreateService();
while (true)
{
Console.WriteLine("The current value of the counter is {0}", counter.GetCount());
Thread.Sleep(5000);
}
}
}
}
从上面的代码我们可以看到,我们希望使用的远程对象的Proxy(counter),是通过另一个SongleCall Proxy(counterFactory)获得的。
下面来运行,从输出结果来看,和我们平常使用的SAO方式的结果没有什么两样——同一个Proxy之间的调用状态被保留。
相关章节:
[原创]我所理解的Remoting(1):Marshaling & Activation - Part I
[原创]我所理解的Remoting(1):Marshaling & Activation - Part II
[原创]我所理解的Remoting(2):远程对象生命周期的管理—Part I
[原创]我所理解的Remoting (2) :远程对象的生命周期管理-Part II
[原创]我所理解的Remoting(3):创建CAO Service Factory使接口和实现相互分离
[原创].NET Remoting: 如何通过Remoting实现双向通信(Bidirectional Communication)
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
我所理解的Remoting(3):创建CAO Service Factory使接口和实现相互分离相关推荐
- 修炼内功——理解函数栈帧创建和销毁
函数栈帧 1. 全局观: 今天我们讲的是栈区,以下的图上方是低地址,下方是高地址,跟上图相反,因此使用顺序是从下方到上方,跟上图本质上一致. 2. 函数的调用关系 ebp,esp这两个寄存器中存放的是 ...
- 创建型模式——Factory Method(未完)
当对某个对象的实例化代码散布在整个项目中的时候,似乎你已经可以嗅到坏味道了,我们叫做"创建蔓延".除非你肯定这个对象的实例化方法永远不会改变,否则最后将"创建的知识搬迁到 ...
- SAP创建Web Service以及用ABAP调用
如果运行 soamanager 打不开,网页显示 devaix .zhongpin.com ,打开 C :\WINDOWS\system32\drivers\etc, 用记事本打开 hosts 文件 ...
- 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式(转载)
源地址:http://doc.chinaunix.net/python/200703/202210.shtml 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式 ...
- 线程创建方式3-实现 callable接口(Java)
线程创建方式3-实现 callable接口(Java) 线程创建方式三:实现 callable接口 callable的好处: 1.可以定返回值 2.可以抛出异常 package src.Demo02; ...
- 【windows service】C# 创建Windows Service(Windows服务)程序
C# 创建Windows Service(Windows服务)程序 很多年前大概08年做了一个windows桌面程序推送邮件给用户的程序,然后通过windows 计划任务每隔N分钟重复执行. 今天闲暇 ...
- 如何用C#创建Windows Service
在.Net中用C#创建Windows Service,其实很简单,按照以下的步骤就可以做出一个简单的Windows Service. 1.首先在创建工程的时候选择Windows Service,这样. ...
- C# 创建Windows Service(Windows服务)程序
工具: Visual Studio Community 2015 写在前面: Windows可以在后台做一些任务,今天分享下Windows Service创建.安装.调试的方法以及一些异常问题的处理 ...
- python catia 接口_如何使用自己创建的CATIA V5自动化接口与Python?
我为catiav5创建了自己的自动化接口.我的接口实现了一个CAA接口. 下面是SetComment方法的示例实现.CAIAinterface是个假名字// MyXYZClass : SetComme ...
- 创建一个 Dog 类继承 Thread ,每 2 秒叫一次(汪汪汪!!),创建一个 Cat 实现 Runnable 接口,每 3 秒求抚摸一次(主人快摸摸我!!),主函数(主线程)从 1 输出到 10
题目:创建一个 Dog 类继承 Thread ,每 2 秒叫一次(汪汪汪!!),创建一个 Cat 实现 Runnable 接口,每 3 秒求抚摸一次(主人快摸摸我!!),主函数(主线程)从 1 输出到 ...
最新文章
- 阿里云服务器CentOS7版本yum方式安装mysql
- java wed登录面 代码_Java Web用户登录实例代码
- 将 WinForms 应用从 .NET Core 3.0 升级到 3.1
- 为什么梯度反方向是函数下降最快的方向
- 国家开放大学2021春1295社会心理学(本)题目
- 起步难、评职称难、压力大!青年科研人员“心病”问题亟待关注!
- springBoot 通过使用log4j2
- 老板想okr,员工想kpi
- hadoop 概要
- (进阶)LeetCode(119)——杨辉三角 II(JavaScript)
- MindManager思维导图中文版免费下载使用教程
- Training_model(2)
- Java面向对象编程三大特征 - 封装
- 新乡医学院三全学院赴范县历史成就观察团
- java 中文词性标注_使用opennlp进行词性标注
- juniper认证(JNCIA,JNCIS,JNCIP,JNCIE)介绍
- 中国普通魔方行业市场供需与战略研究报告
- Python爬虫实战之抓取猫眼电影
- 数据错误(循环冗余检查) 各种解决方法
- 台式电脑点关闭计算机关不了,台式电脑关机关不了怎么办
热门文章
- 不需要数据库的php迷你博客程序,GitHub - Smilefish0/miniblog: 一个不需要数据库、轻量级、微型、开源的博客程序!...
- python圣诞节祝福_Pyhton表白代码——浪漫圣诞节
- ICE笔记(02):简单的ICE通信应用-Hello World
- Video Understanding(2)——Temporal Action Detection时序动作检测
- zblog模板php免费三栏,天兴工作室三栏布局zblog模板 自定义配色
- Scrapy入门案例,抓取美剧天堂的前100最新
- 数据结构队列的代码实现
- 知识点:vs2017 git 操作重置、还原、挑拣对比
- 计蒜客 - 青出于蓝胜于蓝
- 系统管理服务器名,服务器管理系统排名