C# 序列化异常

allen0118 2011-07-21 11:30:31
我在网上找了一个类似QQ的程序,我想研究一下里面通讯方面的技术,然后自己新建了一个项目仿照练习一下


但是发现一个问题,我新建的项目跟在网上下载的完全是独立的,有一些类是复制过来的,项目名称也是重新

定义的,
但是运行过程中总是提示找不到一个程序集,这个程序集居然就是原来那个项目里面的EXE文件,我就奇怪了,

我找了很久,
调试了一次又一次,但是根本找不到到底是哪里用到了原来的那个文件。

错误信息:
Unable to find assembly 'LanMsg, Version=1.0.1.1, Culture=neutral, PublicKeyToken=null'.

其中 LanMsg 就是原来那个项目的执行文件。


错误截图:
http://hi.csdn.net/space-300592-do-album-picid-863089.html

http://hi.csdn.net/space-300592-do-album-picid-863088.html

请大家帮忙看看是哪里出了问题.
...全文
222 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ycproc 2011-07-21
  • 打赏
  • 举报
回复
版本的问题

版本不对
xuexiaodong2009 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 chenpeng0118 的回复:]

引用 1 楼 isjoe 的回复:
是因为二进制序列化导致的

客户端和服务器虽然都是用同一个类作为传递信息的载体,但是。net的序列化有个问题
就是虽然是同一个类在服务器端序列化后传递到客户端后用同样的代码反序列化会导致失败
这是因为在服务器端序列化的时候和客户端反序列化的时候不是同一个程序集导致的。

将序列化和反序列化功能封装成一个DLL,同时在服务器和客户端引用可以消除这个……
[/Quote]就是把共有的东西做成类库,服务端,客户端添加引用
allen0118 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 isjoe 的回复:]
是因为二进制序列化导致的

客户端和服务器虽然都是用同一个类作为传递信息的载体,但是。net的序列化有个问题
就是虽然是同一个类在服务器端序列化后传递到客户端后用同样的代码反序列化会导致失败
这是因为在服务器端序列化的时候和客户端反序列化的时候不是同一个程序集导致的。

将序列化和反序列化功能封装成一个DLL,同时在服务器和客户端引用可以消除这个问题。
还有一个方法就是在反序列化的时……
[/Quote]



能麻烦你指点一下具体该怎么去封装在一起啊,感谢!
isjoe 2011-07-21
  • 打赏
  • 举报
回复
是因为二进制序列化导致的

客户端和服务器虽然都是用同一个类作为传递信息的载体,但是。net的序列化有个问题
就是虽然是同一个类在服务器端序列化后传递到客户端后用同样的代码反序列化会导致失败
这是因为在服务器端序列化的时候和客户端反序列化的时候不是同一个程序集导致的。

将序列化和反序列化功能封装成一个DLL,同时在服务器和客户端引用可以消除这个问题。
还有一个方法就是在反序列化的时候重写一个序列化借口指定返回的程序集信息即可。
allen0118 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 isjoe 的回复:]
是因为二进制序列化导致的

客户端和服务器虽然都是用同一个类作为传递信息的载体,但是。net的序列化有个问题
就是虽然是同一个类在服务器端序列化后传递到客户端后用同样的代码反序列化会导致失败
这是因为在服务器端序列化的时候和客户端反序列化的时候不是同一个程序集导致的。

将序列化和反序列化功能封装成一个DLL,同时在服务器和客户端引用可以消除这个问题。
还有一个方法就是在反序列化的时……
[/Quote]



确实跟你说的一样,客户端和服务器端都去调用那个序列化的方法会有一些异常,我重新新建了一个工程就没有那个提示找不到程序集的问题了,
序列化的函数我封装在SerializersDLL这个DLL文件里面,但是下面的代码总是取不到值,变量 msg 总是Null,

private void DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port) //当有数据到达后的处理进程
{
try
{

MSG.Server.Controls.ClassMsg msg = new SerializersDLL.Serializers().DeSerializeBinary2((new System.IO.MemoryStream(Data))) as MSG.Server.Controls.ClassMsg;
switch (msg.MsgInfoClass)
{
case 1:
UserLoginMsg(msg, Ip, Port);
break;
case 2:
updateUserState(msg, Ip, Port);
break;
}
}
catch (Exception e)
{ }

}
isjoe 2011-07-21
  • 打赏
  • 举报
回复
我也做过socket,用的是二进制序列化。net类,其实第一种方法更好一些。


#region -方法

/// <summary>
/// 序列化TcpMessage对象
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
// 采用二进制序列化取代了XML序列化,二进制体积小,速度快,但是有一定的限定条件
public static byte[] GetMessageByte_(TcpMsg Msg)
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter brFormatter = new BinaryFormatter();
brFormatter.Serialize(memStream, Msg);
return memStream.ToArray();

//XmlSerializer xs = new XmlSerializer(typeof(TcpMsg));
//xs.Serialize(memStream, Msg);
//return memStream.ToArray();
}
}

/// <summary>
/// 反序列化TcpMessage对象
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
// 采用二进制序列化取代了XML序列化,二进制体积小,速度快,但是有一定的限定条件
public static TcpMsg GetMessage_(byte[] Msg)
{
try
{
using (MemoryStream memStream = new MemoryStream(Msg))
{
BinaryFormatter brFormatter = new BinaryFormatter();
// 此接口可以强制转换反序列化程序集的名称信息。
brFormatter.Binder = new ConvertAssemblyBinder();
TcpMsg tm = (TcpMsg)brFormatter.Deserialize(memStream);

//XmlSerializer xs = new XmlSerializer(typeof(TcpMsg));
//TcpMsg tm = xs.Deserialize(memStream) as TcpMsg;
return tm;
}
}
catch (Exception)
{
return null;
}
}

/// <summary>
/// 序列化CSFTcpMsg对象,并附加前缀包大小
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
public static byte[] GetMessageByteEx(TcpMsg Msg)
{
byte[] MsgData = TcpMsg.GetMessageByte_(Msg);
byte[] sendData = new byte[4 + MsgData.Length];
byte[] DataLeg = BitConverter.GetBytes(MsgData.Length);
Array.Copy(DataLeg, 0, sendData, 0, DataLeg.Length);
Array.Copy(MsgData, 0, sendData, DataLeg.Length, MsgData.Length);
return sendData;
}

/// <summary>
/// 反序列化带有大小前缀的byte数组到CSFTcpMsg对象数组(可能是一个对象,也可能是多个)
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
public static TcpMsg[] GetMessageEx(byte[] Msg)
{
try
{
List<TcpMsg> list = new List<TcpMsg>();
byte[] CSFData = null;
int nPosition = 0;
while (nPosition < Msg.Length)
{
// 读取数据头的包大小
CSFData = new byte[BitConverter.ToInt32(Msg, nPosition)];
nPosition += 4;
// 读取包数据
Array.Copy(Msg, nPosition, CSFData, 0, CSFData.Length);
nPosition += CSFData.Length;
TcpMsg CSFmsg = TcpMsg.GetMessage_(CSFData);
if (CSFmsg != null)
{
list.Add(CSFmsg);
}
else
{
return null;
}
}
return list.ToArray();
}
catch (Exception)
{
return null;
}
}

/// <summary>
/// 转换Base64到文本
/// </summary>
/// <param name="Data"></param>
/// <returns></returns>
public static string GetText(byte[] Data)
{
return System.Text.Encoding.ASCII.GetString(Data);
}

/// <summary>
/// 转换文本到Base64
/// </summary>
/// <param name="Data"></param>
/// <returns></returns>
public static byte[] GetBase64(string Data)
{
return System.Text.Encoding.ASCII.GetBytes(Data);
}

#endregion



#region -控制将序列化对象绑定到类型的过程

/// <summary>
/// 控制将序列化对象绑定到类型的过程
/// </summary>
public sealed class ConvertAssemblyBinder : SerializationBinder
{
/// <summary>
/// 控制二进制序列化类型转换
/// </summary>
/// <param name="assemblyName"></param>
/// <param name="typeName"></param>
/// <returns></returns>
// 在序列化过程中,格式化程序传输创建正确类型和版本的对象的实例所需的信息。
// 此信息通常包括对象的完整类型名称和程序集名称。
// 程序集名称包含程序集的名称、版本和强名称(请参见具有强名称的程序集)散列。
// 默认情况下,反序列化将使用此信息创建等同对象的实例(安全策略所限制的任何程序集加载属于例外)。
// 因为类已经在程序集之间移动或者因为在服务器和客户端上要求类的不同版本,有些用户需要控制要加载哪些类。
// 这是一个抽象基类。所有联编程序都扩展此类。
// 给继承者的说明 从 SerializationBinder 继承时,必须重写以下成员:BindToType。

// 由于服务器和客户端共同使用同一个类型,进行数据传递,但是服务器和客户端的同一类型处于不同的
// 程序集,需要在反序列化的时候,提供强制类型转换
public override Type BindToType(string assemblyName, string typeName)
{
// 取得当前的程序集名称,取得传递过来,类型名称不修改,都是"TestPro.CSFTcpMsg"
string strCurAssembly = Assembly.GetExecutingAssembly().FullName;

// 返回当前对应的类型
Type CurType = Type.GetType(String.Format("{0}, {1}", typeName, strCurAssembly));
return CurType;
}
}

#endregion
aXen 2011-07-21
  • 打赏
  • 举报
回复
.net中的exe也是程序集阿,猜测可能是程序集版本不对。

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧