C# 序列化代码导致未处理的异常

C# 序列化代码导致未处理的异常,c#,serialization,autocad,unhandled-exception,autocad-plugin,C#,Serialization,Autocad,Unhandled Exception,Autocad Plugin,我试图创建一个可以将类库序列化和反序列化为AutoCAD图形的代码。这个问题与AutoCAD没有什么关系,只是我无法用常规方法调试它的原因。我从开始这个项目,并成功地让他的代码运行。无论他的代码是如何构造的,它都需要我让我的所有类继承自他的baseobject。由于这显然是一种代码味道,我知道我需要创建一个接口。下面是我最终得到的代码 第一部分是负责在AutoCAD图形中进行序列化的代码 第二部分是实现自定义序列化接口的类的示例 public class Commands { publi

我试图创建一个可以将类库序列化和反序列化为AutoCAD图形的代码。这个问题与AutoCAD没有什么关系,只是我无法用常规方法调试它的原因。我从开始这个项目,并成功地让他的代码运行。无论他的代码是如何构造的,它都需要我让我的所有类继承自他的baseobject。由于这显然是一种代码味道,我知道我需要创建一个接口。下面是我最终得到的代码

第一部分是负责在AutoCAD图形中进行序列化的代码

第二部分是实现自定义序列化接口的类的示例

public class Commands
{
    public class MyUtil
    {

        const int kMaxChunkSize = 127;

        public ResultBuffer StreamToResBuf(MemoryStream ms, string appName)
        {

            ResultBuffer resBuf = new ResultBuffer(new TypedValue((int)DxfCode.ExtendedDataRegAppName, appName));

            for (int i = 0; i < ms.Length; i += kMaxChunkSize)
            {

                int length = (int)Math.Min(ms.Length - i, kMaxChunkSize);

                byte[] datachunk = new byte[length];

                ms.Read(datachunk, 0, length);

                resBuf.Add(new TypedValue((int)DxfCode.ExtendedDataBinaryChunk, datachunk));
            }

            return resBuf;
        }

        public MemoryStream ResBufToStream(ResultBuffer resBuf)
        {

            MemoryStream ms = new MemoryStream();

            TypedValue[] values = resBuf.AsArray();

            // Start from 1 to skip application name

            for (int i = 1; i < values.Length; i++)
            {

                byte[] datachunk = (byte[])values[i].Value;

                ms.Write(datachunk, 0, datachunk.Length);

            }

            ms.Position = 0;

            return ms;

        }

        public void NewFromEntity(IClearspanSerializable objectToSave, Entity ent)
        {

            using (ResultBuffer resBuf = ent.GetXDataForApplication("Member"))
            {
                BinaryFormatter bf = new BinaryFormatter();

                bf.Binder = new MyBinder();

                MemoryStream ms = this.ResBufToStream(resBuf);
                objectToSave.SetObjectData(bf.Deserialize(ms));
            }

        }


        public void SaveToEntity(IClearspanSerializable objectToSave, Entity ent)
        {

            // Make sure application name is registered
            // If we were to save the ResultBuffer to an Xrecord.Data,
            // then we would not need to have a registered application name

            Transaction tr = ent.Database.TransactionManager.TopTransaction;

            RegAppTable regTable = (RegAppTable)tr.GetObject(ent.Database.RegAppTableId, OpenMode.ForWrite);

            if (!regTable.Has("Member"))
            {
                RegAppTableRecord app = new RegAppTableRecord();

                app.Name = "Member";

                regTable.Add(app);

                tr.AddNewlyCreatedDBObject(app, true);
            }


            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();

            bf.Serialize(ms, objectToSave);
            ms.Position = 0;

            ent.XData = this.StreamToResBuf(ms, "Member");;


        }
    }

    public sealed class MyBinder : SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            return Type.GetType(string.Format("{0}, {1}",

              typeName, assemblyName));
        }
    }


    [CommandMethod("SaveClassToEntityXData", CommandFlags.Modal)]
    public void SaveClassToEntityXData(IClearspanSerializable objectToSerialize)
    {

        Database db = Application.DocumentManager.MdiActiveDocument.Database;
        Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

        PromptEntityResult per = ed.GetEntity("Select entity to save class to:\n");

        if (per.Status != PromptStatus.OK)
            return;

        MyUtil util = new MyUtil();



        // Save it to the document
        using (Transaction tr = db.TransactionManager.StartTransaction())
        {

            Entity ent = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForWrite);

            util.SaveToEntity(objectToSerialize, ent);

            tr.Commit();
        }

        // Write some info about the results

        //ed.WriteMessage("Content of MyClass we serialized:\n {0} \n", mc.ToString());

    }


    [CommandMethod("GetClassFromEntityXData", CommandFlags.Modal)]
    public void GetClassFromEntityXData(IClearspanSerializable objectToRestore)
    {

        Database db = Application.DocumentManager.MdiActiveDocument.Database;
        Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

        MyUtil util = new MyUtil();

        PromptEntityResult per = ed.GetEntity("Select entity to get class from:\n");

        if (per.Status != PromptStatus.OK)
            return;

        // Get back the class
        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            Entity ent = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);
            util.NewFromEntity(objectToRestore, ent);

            tr.Commit();

        }

    }
} 
当我尝试在AutoCAD中运行代码时,得到的只是此错误。这让我相信在初始化类时有一个简单的bug。我的断点中没有一个被击中

我应该如何调试它?我在哪里搞砸了初始化

[编辑]-以下是“详细信息”中的内容:


黑暗中拍摄:您需要一个默认构造函数,因为其他人构造了您的对象:

public MattMember()
{

}
或者像这样的特殊反序列化构造函数:

    protected MattMember(SerializationInfo info, StreamingContext context)
    {
// Set object data    
    } 
可能您的接口还需要从ISerializable继承

   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
正确解释堆栈跟踪非常重要。你发布的代码都没有涉及,它从来没有开始过。当AutoCAD尝试调用命令处理程序时,此操作失败:

[CommandMethod("GetClassFromEntityXData", CommandFlags.Modal)]
public void GetClassFromEntityXData(IClearspanSerializable objectToRestore)
// etc..
AutoCAD不会给您那个objectToRestore参数,它不知道您的接口。这就是异常的意思,它不能将委托绑定到具有神秘参数的方法。请注意,从中启动的示例代码如何使用不带参数的方法。以及它如何使用Editor.GetEntity()允许用户拾取图形实体。我假设您需要类似的方案,但我对AutoCAD脚本了解不够

System.ArgumentException:无法绑定到目标方法,因为其 签名或安全透明度与 委托类型

我的理解是,您的接口的“GetObjectData”方法与ISerializable方法冲突,在BinnaryFormatter kitchen的某个地方
只需重构MyUtil中的所有转换函数(StreamToResBuf、ResBufToStream…),就可以序列化/反序列化任何标记有[Serializable]属性的类。
您的虚拟类应该如下所示(集合和基元类型是自动序列化的,仅在需要时实现ISerializable):

最后是你的命令:

[CommandMethod("GetClassFromEntityXData", CommandFlags.Modal)]
//Updated return type here but don't know if it is correct with AutoCAD
public object GetClassFromEntityXData()
{
    Database db = Application.DocumentManager.MdiActiveDocument.Database;
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    object objectToRestore;

    MyUtil util = new MyUtil();

    PromptEntityResult per = ed.GetEntity("Select entity to get class from:\n");

    if (per.Status != PromptStatus.OK)
        return;

    // Get back the class
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        Entity ent = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);
        //Cast to your IClearspan interface here, or use Reflection
        // to determine deserialized object's Type
        objectToRestore = util.NewFromEntity(ent);

        tr.Commit();
    }

    return objectToRestore;
}
实现该命令的函数不能接受参数,但在命令实现内部,可以使用命令行输入函数(如GetString()、GetInteger()等)接受参数,这些函数可以在编辑器类下找到


中,请先单击详细信息按钮,然后将详细信息粘贴到帖子中。我想知道为什么这个问题会得到5票以上……这是什么版本/位的AutoCAD?这是32位Windows 7机器上的AutoCAD 2015
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
[CommandMethod("GetClassFromEntityXData", CommandFlags.Modal)]
public void GetClassFromEntityXData(IClearspanSerializable objectToRestore)
// etc..
[Serializable]
public class MattMember
{
    public string Name;
    List<int> MattsInts;
}
    public object NewFromEntity(Entity ent)
        {    
            using (ResultBuffer resBuf = ent.GetXDataForApplication("Member"))
            {
                BinaryFormatter bf = new BinaryFormatter();

                bf.Binder = new MyBinder();

                MemoryStream ms = this.ResBufToStream(resBuf);
                return bf.Deserialize(ms);
            }    
        }
[CommandMethod("GetClassFromEntityXData", CommandFlags.Modal)]
//Updated return type here but don't know if it is correct with AutoCAD
public object GetClassFromEntityXData()
{
    Database db = Application.DocumentManager.MdiActiveDocument.Database;
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    object objectToRestore;

    MyUtil util = new MyUtil();

    PromptEntityResult per = ed.GetEntity("Select entity to get class from:\n");

    if (per.Status != PromptStatus.OK)
        return;

    // Get back the class
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        Entity ent = (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);
        //Cast to your IClearspan interface here, or use Reflection
        // to determine deserialized object's Type
        objectToRestore = util.NewFromEntity(ent);

        tr.Commit();
    }

    return objectToRestore;
}
[CommandMethod("SaveClassToEntityXData", CommandFlags.Modal)]
public void SaveClassToEntityXData(IClearspanSerializable objectToSerialize)