remoting中的序列化问题

现在做一个remoting的小东西,我的项目构成是这样的,如图:

2009032518341971.jpg

在AttendanceManage类库中Attendance.cs是数据访问类。Base类库主要是写一个抽象父类,并由Attendance继承。AttendanceInfo.cs是实体类。下面的控制台应用程序相当于服务器端。

首先,在AttendanceInfo.cs代码如下:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Base
{
    [Serializable]
    
public class AttendanceInfo : MarshalByRefObject
    {
        
/// <summary>
        
/// 出勤编号
        
/// </summary>
        
        
public int AttendanceID
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 学生学号
        
/// </summary>
        public string StudentCode
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 班级编号
        
/// </summary>
        public int ClassID
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 所属学期
        
/// </summary>
        public int SemesterID
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 所学课程
        
/// </summary>
        public int CourseID
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 出勤情况
        
/// </summary>
        public string Situation
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 出勤日期
        
/// </summary>        
        public DateTime AttendanceTime
        {
            
set;
            
get;
        }
        
/// <summary>
        
/// 出勤备注
        
/// </summary>     
        public string AttendanceDesc
        {
            
set;
            
get;
        }
    }
}

AttendanceBase.cs代码如下:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Base
{
    [Serializable]
    
public abstract class AttendanceBase : MarshalByRefObject
    {
        
public abstract int InsertAttendance(AttendanceInfo model);
        
public abstract string get(int i);
    }
}

Attendance.cs代码如下:(类库已经正确引用)

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Base;


namespace AttendanceManage
{
    [Serializable]
    
public class Attendance : AttendanceBase
    {
        SqlHelper helper;
        
public Attendance()
        {
            helper 
= new SqlHelper();
        }
        
/// <summary>
        
/// 
        
/// </summary>
        
/// <param name="model"></param>
        
/// <returns></returns>
        public override int InsertAttendance(AttendanceInfo model)
        {
            
            SqlParameter[] parm 
= new SqlParameter[]
            {
                
new SqlParameter("@situation",SqlDbType.VarChar),
                
new SqlParameter("@attendancetime",SqlDbType.DateTime),
                
new SqlParameter("@attendanceDesc",SqlDbType.VarChar)
            };
            parm[
0].Value = model.Situation;
            parm[
1].Value = model.AttendanceTime;
            parm[
2].Value = model.AttendanceDesc;
            parm[
0].Direction = ParameterDirection.Input;
            parm[
1].Direction = ParameterDirection.Input;
            parm[
2].Direction = ParameterDirection.Input;
            Console.WriteLine(
"服务器端运行dot.gif");
            
return helper.ExecuteNonQuery("pro_AllAttendance", parm, CommandType.StoredProcedure);
        }
        
/// <summary>
        
/// 
        
/// </summary>
        
/// <returns></returns>
        public override string get(int i)
        {
            Console.WriteLine(i);
            
return "aaaaaabbbbbbbbbbbbbbbbb";
        }
    }
}

SqlHelper.cs就不用看了。

 

控制台应用程序中,App.config

 

ContractedBlock.gif ExpandedBlockStart.gif Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<connectionStrings>
        
<add name="ConnectionString" connectionString="server=192.168.8.105;uid=sa;pwd=000000;database=AttendanceManage" />
    
</connectionStrings>
    
<system.runtime.remoting>
        
<application>
            
<service>
                
<wellknown type="AttendanceManage.Attendance,AttendanceManage" objectUri="Attendance" mode="SingleCall"/>
                
            
</service>
            
<channels>
                
<channel ref="http" port="1234">
                    
<serverProviders>
                        
<provider ref="soap" typeFilterLevel="Full"/>                        
                    
</serverProviders>
                    
<!--<clientProviders>
                        
<provider ref="binary"/>
                    
</clientProviders>-->
                
</channel>                
            
</channels>            
        
</application>
    
</system.runtime.remoting>
</configuration>

Program.cs代码如下:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;

namespace ConsoleApplication1
{
    
class Program
    {
        
static void Main(string[] args)
        {
            RemotingConfiguration.Configure(
"ConsoleApplication1.exe.config"false);
            Console.WriteLine(
"aaaaaaaaaa");
            Console.ReadLine();
        }
    }
}

在这里,服务器端代码完毕。

 

来看客户端:

客户端很简单,使用控制台应用程序,先将Base.dll添加应用,配置下APP.CONFIG:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<system.runtime.remoting>
        
<application>
            
<client>
                
<wellknown type="AttendanceManage.AttendanceBase,AttendanceManage" url="http://localhost:1234/AttendanceBase" />
            
</client>
            
<channels>
                
<channel ref="soap">        
                    
                
</channel>
            
</channels>
        
</application>
    
</system.runtime.remoting>
</configuration>

在客户端的program.cs中代码如下:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Serialization;
using System.IO;
namespace timeclient
{
    
class Program
    {
        
static void Main(string[] args)
        {

            
            Base.AttendanceBase ba 
= (Base.AttendanceBase)Activator.GetObject(typeof(Base.AttendanceBase), "http://localhost:1234/Attendance");
            Base.AttendanceInfo bai 
= new Base.AttendanceInfo();
            bai.Situation 
= "出勤";
            bai.AttendanceTime 
= DateTime.Now;
            bai.AttendanceDesc 
= "客户端测试";
            FileStream fs 
= new FileStream("model.xml", FileMode.Create);
            System.Xml.Serialization.XmlSerializer x 
= new System.Xml.Serialization.XmlSerializer(typeof(Base.AttendanceInfo));
            x.Serialize(fs, bai);

            Console.WriteLine(ba.InsertAttendance(bai));
            Console.WriteLine(ba.
get(11));//这句可以正常执行
            Console.ReadLine();
        }
    }
}

此时,问题来了,最先,我在服务器端的App.config文件中并没有写:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
<serverProviders>
                        
<provider ref="soap" typeFilterLevel="Full"/>                        
                    
</serverProviders>

这时,报出一个安全什么的错误来,我查了查,貌似是需要填写上面的代码即可,我也写了,也过去了。

————————————————分割线,总结——————————————

 

我这样写的目的是,分离出一个抽象类来,使用实体类继承抽象类,当客户端引用DLL时,只是引用抽象类的DLL,根本拿不到实体类的DLL。其实重要的的配置文件的配置和这句:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
Base.AttendanceBase ba = (Base.AttendanceBase)Activator.GetObject(typeof(Base.AttendanceBase), "http://localhost:1234/Attendance");

要确定确实调用的是服务器端方法。而不是本地引用的DLL中的方法。

————————分割线,提出问题————————

 

 

结果一运行又出了一个问题,那就是当我实例化实体类对象,并往对象属性中传值后,希望将此对象传递给服务器端方法进行相应操作,结果出了这样的错误:

2009032518525375.jpg

说实话,我很惊讶,并不太清楚怎么回事。个人感觉,可能是由于在客户端传递对象时,没有进行序列化的原因。

 

既然需要进行序列化,那么就序列化吧,打算将对象序列化成XML格式,就是这几句

 

ContractedBlock.gif ExpandedBlockStart.gif Code
FileStream fs = new FileStream("model.xml", FileMode.Create);
            System.Xml.Serialization.XmlSerializer x 
= new System.Xml.Serialization.XmlSerializer(typeof(Base.AttendanceInfo));
            x.Serialize(fs, bai);

成是成了,但是我如何传递呢?那不是需要将XML格式的字符串传递到服务器端,在进行反序列化么?

 

但是这样就失去了我的本意了啊,我是打算将实体类型的对象传递过去到服务器端的,按照较为传统的方式传递。

就是InsertAttendance()方法中的参数还是AttendanceInfo格式的。

————————解决方案——————————

回复中5楼朋友【@yuguohua】 解答:

因為 AttendanceInfo : MarshalByRefObject
所以bai 的instance是建立在client, 當bai傳至server時, 只有reference.要讀取bai的內容時, 須再與client溝通, 而client並沒有提供溝通channel.

請把 MarshalByRefObject 拿掉就可以解決問題.

————————————————
6楼朋友【@一叶一菩提,一花一世界 】解答:

很简单,我跟你调了一下结果把一个dll的名字写错了,搞了我个把小时,nnd,真郁闷啊,看来晚上不适宜看程序。

你所有的server端的类都即继承自MarshalByRefObject 又把它mark成Serializable,这里太乱,你说它在rpc的时候到底是By Value还是By Reference呢? 这个就不得而知了,我也不知道,如果这样的romting的框架会怎么样去选择,如果它也不知道哦怎么选择,那它不就要出错了么?哈哈

你可以把AttendanceInfo这个类就Mark成Serializable,然后把AttendanceBase继承与自MarshalByRefObject,Attendance继承自AttendanceBase(去掉Serializable)就好了。

哈哈,你要用remoting,就要明明白白的告诉Remoting Framework你到底想干什么?By Value or By

————————————————————

上面两位的解决方案是正确的,在此感谢2位。

转载于:https://www.cnblogs.com/fengyishou/archive/2009/03/25/1421658.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值