本系列的全部源代码及二进制文件可以从这里下载:IocInCSharp.rar øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
本部分示例代码请参考"src\Step5"目录øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
六、利用Ioc在不修改任何原有代码的情况下实现Remoting上文我们提到,为了实现对HelloGenerator.dll的分布式调用,我们不得不修改了原有程序的多处代码。那么有没有可能在不动任何原有代码的情况下,单纯靠添加组件、修改配置文件实现远程访问呢?当然可以。这次我们还是使用Spring.net完成这个工作。 经过调整后的系统组件构成如下图所示:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
该方案没有修改“src\Step3”中的任何代码,仅仅通过修改配置文件和添加了若干个组件就实现了远程访问。修改方案如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(1)使用Proxy模式代理原有HelloGenerator如果要让某个对象具有分布式的功能,必须使其继承自MarshalByRefObject。但是由于不能修改任何原有代码,所以这次我们只能绕道而行, 借助Proxy模式代理原有的HelloGenerator。在RemotingServer项目中,我们定义了一个新类HelloGeneratorProxy继承自MarshalByRefObject,通过委派的方式对原有的HelloGenerator进行调用,代码如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
namespace IocInCSharp{øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  public class HelloGeneratorProxy : MarshalByRefObject, IHelloGeneratorøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      private IHelloGenerator _helloGen;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      public IHelloGenerator HelloGeneratorøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        get { return _helloGen; }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        set { _helloGen = value; }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      public string GetHelloString(string name)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        if(_helloGen != null)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            return _helloGen.GetHelloString(name);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        return null;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
}øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
仔细观察,我们会发现HelloGeneratorProxy持有一个对IHelloGenerator的引用,该属性是可以Set的,因此我们可以借助Ioc的威力,通过调整Sping.net的配置文件动态决定远程服务器究竟发布EnHelloGenerator还是CnHelloGenerator。øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(2)发布HelloGeneratorProxy通过RemotingServer.exe,我们将HelloGeneratorProxy发布出去,客户端实际上调用的是Proxy对象(不用担心,由于“针对接口编程”,客户端只知道它是IHelloGenerator类型对象)。服务器端代码如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Configuration;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Collections;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting.Channels;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting.Channels.Http;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Serialization.Formatters;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using Spring.Context;namespace IocInCSharp{øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  public class ServerøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      public static void Main()øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        int port = Convert.ToInt32(ConfigurationSettings.AppSettings["LocalServerPort"]);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        tryøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            IDictionary props = new Hashtable();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            props["port"] = port;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            props["timeout"] = 2000;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            HttpChannel channel = new HttpChannel(props, clientProvider, serverProvider);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            ChannelServices.RegisterChannel(channel);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            IApplicationContext ctx = ConfigurationSettings.GetConfig("spring/context") as IApplicationContext;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            HelloGeneratorProxy proxy = (HelloGeneratorProxy)ctx.GetObject("myHelloGeneratorProxy");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            RemotingServices.Marshal(proxy, "HelloGenerator.soap");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            Console.WriteLine("Server started!\r\nPress ENTER key to stop the server...");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            Console.ReadLine();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        catchøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            Console.WriteLine("Server Start Error!");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
}øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
注意其中的几条命令:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
IApplicationContext ctx = ConfigurationSettings.GetConfig("spring/context") as IApplicationContext;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
HelloGeneratorProxy proxy = (HelloGeneratorProxy)ctx.GetObject("myHelloGeneratorProxy");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
RemotingServices.Marshal(proxy, "HelloGenerator.soap");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
我们使用Ioc向HelloGeneratorProxy注入具体的HelloGenerator对象,并通过RemotingServices.Marshal(proxy, "HelloGenerator.soap")命令将该实例发布出去。服务器端的配置文件如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
<?xml version="1.0" encoding="utf-8" ?>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
<configuration>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  <configSections>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      <sectionGroup name="spring">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      </sectionGroup>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  </configSections>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  <spring>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      <context>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <resource uri="config://spring/objects" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      </context>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      <objects xmlns="http://www.springframework.net">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="myHelloGeneratorProxy" type="IocInCSharp.HelloGeneratorProxy, RemotingServer">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="HelloGenerator">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <ref object="myCnHelloGenerator" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="myEnHelloGenerator" type="IocInCSharp.EnHelloGenerator, HelloGenerator" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="myCnHelloGenerator" type="IocInCSharp.CnHelloGenerator, HelloGenerator" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      </objects>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  </spring>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  <appSettings>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      <add key="LocalServerPort" value="8100" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  </appSettings>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
</configuration>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
用户可以尝试将配置文件中<ref object="myCnHelloGenerator" />更改为<ref object="myEnHelloGenerator" />,重新启动服务后看看客户端调用结果是什么?øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(3)客户端实现技术-1客户端实现起来要麻烦一些。由于不允许修改MainApp中的任何代码,我们必须能够在合适的时机拦截代码运行并创建远程连接,同时确保在Ioc注入时注入的是远程对象。所有这些工作Sping.net都考虑的很周到。它提供了depends-on属性,允许在执行某一操作前强制执行某段代码。在客户端的配置文件中,我们可以看到如下的配置选项:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="mySayHello" type="Spring.Aop.Framework.ProxyFactoryObject" depends-on="force-init">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        .........øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="force-init" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="TargetType" value="IocInCSharp.ForceInit, ForceInit" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="TargetMethod" value="Init" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
这表示,当我们初始化mySayHello时,要先去调用ForceInit.dll文件中ForceInit类的Init方法。ForceInit是一个新编写的类,其主要目的就是创建并注册一个用于远程通讯的Channel。代码实现如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Collections;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting.Channels;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Remoting.Channels.Http;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System.Runtime.Serialization.Formatters;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
namespace IocInCSharp{øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  public class ForceInitøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      public static void Init()øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        //建立连接øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        serverProvider.TypeFilterLevel = TypeFilterLevel.Full;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        IDictionary props = new Hashtable();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        props["port"] = 8199;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        props["name"] = "myHttp";øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        HttpChannel channel = new HttpChannel(props, clientProvider, serverProvider);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        //获得当前已注册的通道;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        IChannel[] channels = ChannelServices.RegisteredChannels;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        //关闭指定名为MyHttp的通道;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        foreach (IChannel eachChannel in channels)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            if (eachChannel.ChannelName == "myHttp")øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              ChannelServices.UnregisterChannel(eachChannel); øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        ChannelServices.RegisterChannel(channel);øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
}øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(4)客户端实现技术-2剩下的工作就是为mySayHello的HelloGenerator注入远程对象。通常情况下我们需要使用Activator.GetObject方法调用远程对象,不过Spring.net已经将其封装起来,我们只需修改一下配置文件,就可以确保调用到远程对象。配置文件对应部分如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="mySayHello" type="Spring.Aop.Framework.ProxyFactoryObject" depends-on="force-init">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="target">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <object id="myLocalSayHello" type="IocInCSharp.SayHello, SayHello">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
                  <property name="HelloGenerator">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
                    <ref object="myHelloGenerator" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
                  </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            ......øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object name="myHelloGenerator" type="Spring.Remoting.SaoFactoryObject, Spring.Services">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="ServiceInterface">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <value>IocInCSharp.IHelloGenerator, ICommon</value>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="ServiceUrl">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <value>[url=http://127.0.0.1100/HelloGenerator.soap%3C]http://127.0.0.1100/HelloGenerator.soap<[/url];/value>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
借助Spring.Remoting.SaoFactoryObject,我们轻松实现了远程对象访问,不必书写一行代码。(目前SAO在Spring.net的实现尚不完整,按照Spring.net帮助手册上的做法,通过配置文件只能实现客户端访问远程对象,还做不到服务器端发布远程对象)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(5)使用AOP拦截调用Sping.net目前已经实现AOP功能,我们可以很容易的对方法进行拦截和调用。需要做的工作就是设计相应的Interceptor,然后修改配置文件。目前Sping.net使用的AOP功能是AopAlliance的实现,因此代码编写时命名空间引用让人感觉多少有些别扭,不是以Sping开头。我编写的MethodInterceptor代码如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using System;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
using AopAlliance.Intercept;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
namespace IocInCSharp{øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  class MethodInterceptor : IMethodInterceptorøÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      public object Invoke(IMethodInvocation invocation)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      {øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        Console.WriteLine("Before Method Call...");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        object returnValue = invocation.Proceed();øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        Console.WriteLine("After Method Call...");øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        return returnValue;øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
      }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  }øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
}øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
在方法调用前打印"Before Method Call...",在方法调用后打印"After Method Call..."。剩下的工作就是修改配置文件,将其应用到相应的方法上。配置文件片断如下:øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="MethodAdvice" type="Spring.Aop.Support.RegexpMethodPointcutAdvisor">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="pattern" value="SayHelloTo" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            <property name="advice">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <object type="IocInCSharp.MethodInterceptor, MethodInterceptor" />øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        <object id="mySayHello" type="Spring.Aop.Framework.ProxyFactoryObject" depends-on="force-init">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
                          ......                                    øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
          <property name="interceptorNames">øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              <list>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
                  <value>MethodAdvice</value>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
              </list>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
            </property>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
        </object>øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
通过以上操作,我们在没有修改任何原有代码的情况下,让原有系统实现了远程分布式访问。øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
请大家访问示例代码的“bin\Step5"目录,下面有3个子目录:Server、Client、WithoutRemoting。首先运行Server目录下的RemotingServer.exe,然后运行Client目录下的MainApp.exe进行远程调用。系统通过Remoting完成远程调用。关闭所有程序后,进入到WithoutRemoting目录,里面有个Readme.txt文件,按照操作步骤将文件: øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Server\HelloGenerator.dll øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Client\MainApp.exe øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Client\ICommon.dll øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Client\SayHello.dll øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Client\Spring.Core.dll øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
..\Client\log4net.dll øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
  øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
拷贝到该目录,再次运行MainApp.exe,你会发现它是一个地地道道的本地应用程序!本地与远程唯一的区别就是配置文件的不同以及增加了几个其它的DLL。这正式我们这个示例的价值体现。øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
到此为止,我们完成了对Ioc应用的一系列模拟。Ioc写得多一些,AOP写得少了点。欢迎大家批评指正。øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø
(全文完)øÕc:Êg°ðÍwww.netcsharp.cn¥3³á¢íÔø