ntchjie 发表于 2009-3-26 14:32:00

本帖最后由 作者 于 2009-3-26 15:28:37 编辑 <br /><br /> gentellu发表于2008-9-9 10:26:00static/image/common/back.gif但直接用Form1启动程序时系列化及反系列化都正常,只是利用CAD来启动Form1进行反系列化时出现异常,我就是不太明白这方面的原因。

<p>就是写成类库(在CAD内调用的dll),就出现异常。</p><p>我也为这个问题困扰很久。</p>

雪山飞狐_lzh 发表于 2009-8-31 20:56:00

这段时间碰巧用了BinaryFormatter序列化/反序列化,
可以实现,但注意不要在初始化例程里反序列化(奇怪的Bug)
贴上代码:)
Command类:
using System;
using System.Reflection;
using Autodesk.AutoCAD.Runtime;

namespace TlsCad.NetAutoLoad
{

   
    public class Command : IComparable
    {

      public string GlobalName;
      public string LocalizedName;
      public string Description;

      public string ModuleName;
      public string TypeName;
      public string MethodName;

      public Command() { }

      public Command(string globalName)
      {
            GlobalName = globalName;
      }


      #region IComparable 成员

      int IComparable.CompareTo(object obj)
      {
            Command cmd = obj as Command;
            return this.GlobalName.CompareTo(cmd.GlobalName);
      }

      #endregion
    }
}CommandCollection类using System;
using System.IO;
using System.Resources;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Autodesk.AutoCAD.Runtime;
namespace TlsCad.NetAutoLoad
{
    public enum AssemblyLoad
    {
      LoadOnStartup = 2,
      LoadByCmd = 12,
      LoadDisabled = 20
    }
   
    public class CommandCollection : ISerializable
    {
      private AssemblyLoad _loadctrls;
      private string _description;
      private List<Command> _cmds = new List<Command>();
      //private List<string> _groups = new List<string>();
      public CommandCollection() { }
      public CommandCollection(SerializationInfo info, StreamingContext ctxt)
      {
            _loadctrls = (AssemblyLoad)info.GetValue("Assembly_LoadCtrls", typeof(AssemblyLoad));
            _description = (string)info.GetValue("Assembly_Description", typeof(string));
            //_groups = (List<string>)info.GetValue("Assembly_Groups", typeof(List<string>));
            _cmds = (List<Command>)info.GetValue("Assembly_Commands", typeof(List<Command>));
      }
      #region ISerializable 成员
      void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
      {
            info.AddValue("Assembly_LoadCtrls", _loadctrls);
            info.AddValue("Assembly_Description", _description);
            //info.AddValue("Assembly_Groups", _groups);
            info.AddValue("Assembly_Commands", _cmds);
      }
      #endregion
      public AssemblyLoad LoadCtrls
      {
            get { return _loadctrls; }
            set { _loadctrls = value; }
      }
      public string Description
      {
            get { return _description; }
            set { _description = value; }
      }
      public void CopyFrom(CommandCollection ai)
      {
            _loadctrls = ai._loadctrls;
            _description = ai._description;
            _cmds = ai._cmds;
      }
      public void Add(Command cmd)
      {
            _cmds.Add(cmd);
      }
      public void Remove(Command cmd)
      {
            _cmds.Remove(cmd);
      }
      public void Sort()
      {
            _cmds.Sort();
      }
      public int Count
      {
            get { return _cmds.Count; }
      }

      public void WriteTo(string path)
      {
            using (Stream stream = File.Open(path, FileMode.Create))
            {
                BinaryFormatter bformatter = new BinaryFormatter();
                bformatter.Serialize(stream, this);
            }
      }
      public void ReadFrom(string path)
      {
            using (Stream stream = File.Open(path, FileMode.Open))
            {
                BinaryFormatter bformatter = new BinaryFormatter();
                CommandCollection cmds = (CommandCollection)bformatter.Deserialize(stream);
                CopyFrom(cmds);
            }
      }
      public void LoadFromAssembly(string path)
      {
            //_groups.Clear();
            _cmds.Clear();
            Assembly assem = Assembly.LoadFrom(path);
            foreach (System.Reflection.Module m in assem.GetModules(true))
            {
                Type[] types = m.GetTypes();
                foreach (Type t in types)
                {
                  ResourceManager rm =
                        new ResourceManager(t.FullName, assem);
                  rm.IgnoreCase = true;
                  MethodInfo[] methods = t.GetMethods();
                  foreach (MethodInfo mi in methods)
                  {
                        object[] attbs =
                            mi.GetCustomAttributes(
                              typeof(CommandMethodAttribute),
                              true
                            );
                        foreach (object attb in attbs)
                        {
                            CommandMethodAttribute cma = attb as CommandMethodAttribute;
                            if (cma != null)
                            {
                              //if (cma.GroupName != null && !_groups.Contains(cma.GroupName))
                              //{
                              //    _groups.Add(cma.GroupName);
                              //}
                              
                              Command cmd = new Command(cma.GlobalName);
                              cmd.ModuleName = m.Name;
                              cmd.TypeName = t.FullName;
                              cmd.MethodName = mi.Name;
                              cmd.LocalizedName = cmd.GlobalName;
                              string lnid = cma.LocalizedNameId;
                              if (lnid != null)
                              {
                                    try
                                    {
                                        cmd.LocalizedName = rm.GetString(lnid);
                                    }
                                    catch
                                    { }
                              }
                              _cmds.Add(cmd);
                            }

                        }
                  }
                }
            }
      }

      //public void Run(Assem assem, Command cmd)
      //{
      //    Assembly assembly = Assembly.LoadFrom(assem.Location);
      //    Module m = assembly.GetModule(cmd.ModuleName);
      //    Type t = m.GetType(cmd.TypeName);
      //    MethodInfo mi = t.GetMethod(cmd.MethodName);
      //    object obj = assembly.CreateInstance(t.FullName);
      //    mi.Invoke(obj, new object);
      //    obj = null;
      //}
      public IEnumerator GetEnumerator()
      {
            return _cmds.GetEnumerator();
      }
    }
}


sieben 发表于 2009-8-31 21:53:00

<p>如版主所说"但注意不要在初始化例程里反序列化",即使相应的类里面没有AutoCAD的类也不行(如没有Point3d等类也不行)</p><p>另外即使不是在初始化的时候,若反序列化的类里面有AutoCAD的类也不行(如Point3d等,在构造函数里面有用到或公用属性)</p><p>会出现楼主这样的问题.(还没看楼主的代码)</p><p>不过这是我两年前AutoCAD2006的记忆了,现在版主说行应该那就是行了(还没看代码也没测试).</p><p>另外有个记忆不管是反射还是反系列化,在处理Point3d这些类时应该用全名,即"Autodesk.AutoCAD.Geometry.Point3d",而不要只写"Point3d"</p><p>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</p><p>不好意思!两年前的事情有点记得不大清楚了!<br/>可能我只涉及了反射方面的问题<br/>反系列化可能试过,但只失败而没成功过,因为我现在找不到成功反序列化的代码</p><p>另外在使用发射方面的技术时,若涉及Point3d等类型的数据我是自己做特殊处理</p>

雪山飞狐_lzh 发表于 2009-8-31 22:02:00

sieben发表于2009-8-31 21:53:00static/image/common/back.gif另外即使不是在初始化的时候,若反序列化的类里面有AutoCAD的类也不行(如Point3d等,在构造函数里面有用到或公用属性)

<p>记得有看到2009版本的序列化Cad对象的代码,Kean的</p><p>应该是2009版本后才支持吧</p>

雪山飞狐_lzh 发表于 2009-9-2 13:13:00

代码更改了一遍,发现了一些问题<br/>似乎有自定义类型和系统类型混用的时候反序列化仍然不成功<br/>不过,加入下面的类,在初始化时也可以反序列化了<br/><br/>    public class UBinder : SerializationBinder<br/>    {<br/>        public override Type BindToType(string assemblyName, string typeName)<br/>        {<br/>            return Type.GetType(typeName);<br/>        }<br/>    } <br/><br/>反序列化时<br/>        public void ReadFrom(string path)<br/>        {<br/>            using (Stream stream = File.Open(path, FileMode.Open))<br/>            {<br/>                BinaryFormatter bformatter = new BinaryFormatter();<br/>                bformatter.Binder = new UBinder();<br/>                Assem cmds = (Assem)bformatter.Deserialize(stream);<br/>                CopyFrom(cmds);<br/>            }<br/>        }<br/>看来不是Bug的问题:)<br/>

ywlm 发表于 2010-9-10 12:26:00

<p>把.dll拖到 "<font face="Verdana">C:\WINDOWS\assembly\"</font>里面就可以反序列化</p>
页: 1 [2]
查看完整版本: 对象反系列化问题