搏客 Winning
After three days without programming, life becomes meaningless
posts - 46,  comments - 41,  trackbacks - 21

项目概述:实现一个最简单的三层分布式应用程序。
    Entity 实体层 (System.Serializable 可序列化)
    1、BizL 业务逻辑层(继承System.EnterpriseServices.ServicedComponent COM+实现事务处理)
    IFacL 业务逻辑的接口层,实现客户端远程访问的接口协议
    2、业务门面层(继承System.MarshalByRefObject实现IFacL.IStuMgeSerV)
    Remoting启动程序(SerV)
    3、远程客户端测试(TerL)

项目IFacl中的业务接口定义,该定义描述了远程提供的服务内容是客户端与服务器交互
的协议,通过此协议客户端可以在没有服务器端完整的类结构的情况下仅通过接口就可以
调用服务器上的远程方法


namespace IFacL
{
    
public interface IStuMgeSerV
    
{
        Entity.Student GetAStudent();
    }

}


项目Entity中的实体定义,Entity是服务器和客户端交互的对象,这个对象必须是
可序列化的并且客户端和服务器端必须同时具有相同的完整的类定义。

namespace Entity
{
    [System.Serializable]
    
public class Student
    
{
        
private string m_name="";
        
public Student(string name)
        
{
            
this.m_name=name;
        }

        
public string Name
        
{
            
get{return this.m_name;}
        }

    }

}

项目BizL的业务具体实现,这个具体实现只存在与服务器端,为了安全性和代码的版权
具体的实现对客户是透明的

namespace BizL
{
    
public class StudentMge :ServicedComponent
    
{
        
public Entity.Student FindAStudent()
        
{
            Entity.Student aStu
=new Entity.Student("Wengmingjun");
            
return aStu;
        }

    }

}

项目BizL的业务具体实现,这个具体实现只存在与服务器端,为了安全性和代码的版权 具体的实现对客户是透明的


项目BizL的业务具体实现,这个具体实现只存在与服务器端,为了安全性和代码的版权 具体的实现对客户是透明的
项目Facl对业务具体实现封装的远程访问接口,为了将服务器上实现业务逻辑的类功能 
清晰化,和将COM+实现的代码包装出一个远程(实现MarshalByRefObject、Remoting)
接口而封装出的一个符合Facade模式的代码

namespace FacL
{
    
public class StuMgeSerV :System.MarshalByRefObject,IFacL.IStuMgeSerV
    
{
        
public Entity.Student GetAStudent()
        
{
            BizL.StudentMge stuMge
=new BizL.StudentMge();
            
return stuMge.FindAStudent();
        }

    }

}

项目SerV的Remoting服务启动,对Remoting服务的启动,这是一个控制台程序

namespace SerV
{
    
class SerVStarter
    
{
        
static void Main(string[] args)
        
{
            System.Runtime.Remoting.RemotingConfiguration.Configure(
"SerV.config");
            System.Console.WriteLine(
"BizServ Running");
            System.Console.Read();
        }

    }

}

服务配置文件 SerV.config 这个文件的格式要注意

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
   
<system.runtime.remoting>
      
<application>
         
<service>
           
<!--模式 类型="类名 程序集名 远程对象引用名"-->
            
<wellknown 
        
mode="Singleton"
        type
="FacL.StuMgeSerV,FacL"
        objectUri
="StuMgeSerV.rem"
            
/>
         
</service>
        
<channels>
           
<channel port="8989" ref="http" />
        
</channels>
        
</application>
   
</system.runtime.remoting>
</configuration>

客户端的远程服务测试程序
使用Activator获得远程对象 使用接口协议来为远程对象造型,并且使用接口协议调用
远程对象

namespace TerL
{
  
class InvokeRM
  
{
    
static void Main(string[] args)
    
{
      System.Runtime.Remoting.RemotingConfiguration.Configure(
"Client.config");
      IFacL.IStuMgeSerV iStuMgeServ
=(IFacL.IStuMgeSerV)System.Activator
      .GetObject(
typeof(IFacL.IStuMgeSerV),"http://192.168.0.17:8989/StuMgeSerV.rem");
      Console.WriteLine(iStuMgeServ.GetAStudent().Name);
      Console.ReadLine();
    }

  }

}

客户调用配置文件Client.config

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
   
<system.runtime.remoting>
      
<application>
         
<client>
               <!--注意下面与服务器的配置是不同的,这样做的目的是使客户可-->
            
<!--以用业务逻辑界面接口调用远程的业务逻辑类-->
            
<wellknown 
          
  type="IFacL.IStuMgeSerV,IFacL"
               url="http://192.168.0.17:8989/StuMgeSerV.rem"
            />
         
</client>
      
</application>
   
</system.runtime.remoting>
</configuration>


附:
======================================================================
COM+注册命令
path=D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin
;C:\WINNT\Microsoft.NET\Framework\v1.1.4322
gacutil /u Entity.dll
gacutil /u BizL.dll
gacutil /i Entity.dll
gacutil /i BizL.dll
pause

AssemblyInfo的配置

using System.Reflection;
using System.Runtime.CompilerServices;
using System.EnterpriseServices;

[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]  

[assembly: ApplicationActivation(ActivationOption.Server )]
[assembly: ApplicationID("F0BA9BCE-133E-4cc2-9541-D72B236AC25B")]
[assembly: ApplicationName("BizL")]
[assembly: Description("BizL")]  
[assembly: ApplicationAccessControl(false )]

[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("..\\..\\BizL.snk")]
[assembly: AssemblyKeyName("")]


SNK文件的产生
sn -k BizL.snk

目录和文件结构
解决方案“L3Demo”(6个项目)
-BizL
  -引用
     .Entity
     .System
     .System.Data
     .System.EnteriseService
     .System.XML
  .AssemblyInfo.cs
  .BizL.snk
  .StudentMge.cs
-Entity
  -引用
     .System
     .System.Data
     .System.EnteriseService
     .System.XML
  .AssemblyInfo.cs
  .Entity.snk
  .Student.cs
-FacL
  -引用
     .BizL
     .Entity
     .IFacL
     .System
     .System.Data
     .System.EnteriseService
     .System.XML
  .StuMgeSerV.cs
-IFacL
    -引用
     .Entity
  .IStuMgeSerV.cs
-SerV
  -引用
     .FacL
     .System
     .System.Data
     .System.EnteriseService
     .System.XML
  .SerV.config
  .SerVstarter.cs
-TerL
  -引用
     .Entity
     .IFacL
     .System
     .System.Data
     .System.EnteriseService
     .System.XML
  .Client.config
  .TerL.cs

posted on 2004-09-08 16:11 搏客 Winning 阅读(2255) 评论(3)  编辑 收藏 所属分类: 项目实践

FeedBack:
2004-09-08 17:21 | 听棠 [未注册用户]
我看了这文章.不错.客户端也要保持实体层.那要是以后实体层更新.如何保持客户端的实体层更新呢??

  回复  引用    
2004-09-08 17:59 | 翁明军的博客      
两种方法:
1、让客户重新下载新的实体类。
2、定义合理的实体的类结构和继承关系,比如在实体中用集合保存数据。
客户端只须保持实体基类即可应变实体的变化。
比如如下的实体基类定义
public class Entity
{
private Hashtable m_data=null;

public Entity()
{
this.m_data=new Hashtable();
}

public string FId
{
get{return DConvert.ToString(GetProperty("FID"));}
set{SetProperty("FID",value);}
}

public Hashtable Data
{
get{return this.m_data;}
}

public object GetProperty(string key)
{
return this.m_data[key.ToUpper()];
}

public void SetProperty(string key,object val)
{
this.m_data[key.ToUpper()]=val;
}
}

public class MyEntity : Entity
{
public string Name
{
get{return DConvert.ToString(GetProperty("NAME"));}
set{SetProperty("NAME",value);}
}

public int Age
{
get{return DConvert.ToInt32(GetProperty("AGE"));}
set{SetProperty("AGE",value);}
}
}
  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-04-12 09:41 编辑过


相关链接:
 




与我联系

搜索

 

常用链接

随笔分类

随笔档案

积分与排名

  • 积分 - 30552
  • 排名 - 1325

最新评论

阅读排行榜