找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1143|回复: 0

[分享] Serialize a .NET class into an AutoCAD drawing database

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-5-4 15:14:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
By Adam Nagy

I would like to serialize my .NET class into an AutoCAD drawing database, so it is saved into the drawing, and I can recreate my class again (deserialize it), when the drawing is reopened. How could I do it?


Solution

You could use the .NET serialization technique to serialize your class into a binary stream and then you can save it in the drawing as a bunch of binary chunks. You could save the ResultBuffer to an object's XData or into an Xrecord.Data of an entity or an item in the Named Objects Dictionary (NOD). DevNote TS2563 tells you what the difference is between using XData and Xrecord. If you are saving it into an XData, then the ResultBuffer needs to start with a registered application name. Here is a sample which shows this:
  1. using System;

  2. using System.Runtime.Serialization;

  3. using System.Runtime.Serialization.Formatters.Binary;

  4. using System.IO;

  5. using System.Security.Permissions;



  6. using Autodesk.AutoCAD.Runtime;

  7. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;

  8. using Autodesk.AutoCAD.DatabaseServices;

  9. using Autodesk.AutoCAD.EditorInput;



  10. [assembly: CommandClass(typeof(MyClassSerializer.Commands))]



  11. namespace MyClassSerializer

  12. {

  13.   // We need it to help with deserialization



  14.   public sealed class MyBinder : SerializationBinder

  15.   {

  16.     public override System.Type BindToType(

  17.       string assemblyName,

  18.       string typeName)

  19.     {

  20.       return Type.GetType(string.Format("{0}, {1}",

  21.         typeName, assemblyName));

  22.     }

  23.   }



  24.   // Helper class to write to and from ResultBuffer



  25.   public class MyUtil

  26.   {

  27.     const int kMaxChunkSize = 127;



  28.     public static ResultBuffer StreamToResBuf(

  29.       MemoryStream ms, string appName)

  30.     {

  31.       ResultBuffer resBuf =

  32.         new ResultBuffer(

  33.           new TypedValue(

  34.             (int)DxfCode.ExtendedDataRegAppName, appName));



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

  36.       {

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

  38.         byte[] datachunk = new byte[length];

  39.         ms.Read(datachunk, 0, length);

  40.         resBuf.Add(

  41.           new TypedValue(

  42.             (int)DxfCode.ExtendedDataBinaryChunk, datachunk));

  43.       }



  44.       return resBuf;

  45.     }



  46.     public static MemoryStream ResBufToStream(ResultBuffer resBuf)

  47.     {

  48.       MemoryStream ms = new MemoryStream();

  49.       TypedValue[] values = resBuf.AsArray();



  50.       // Start from 1 to skip application name



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

  52.       {

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

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

  55.       }

  56.       ms.Position = 0;



  57.       return ms;

  58.     }

  59.   }



  60.   [Serializable]

  61.   public abstract class MyBaseClass : ISerializable

  62.   {

  63.     public const string appName = "MyApp";



  64.     public MyBaseClass()

  65.     {

  66.     }



  67.     public static object NewFromResBuf(ResultBuffer resBuf)

  68.     {

  69.       BinaryFormatter bf = new BinaryFormatter();

  70.       bf.Binder = new MyBinder();



  71.       MemoryStream ms = MyUtil.ResBufToStream(resBuf);



  72.       MyBaseClass mbc = (MyBaseClass)bf.Deserialize(ms);



  73.       return mbc;

  74.     }



  75.     public static object NewFromEntity(Entity ent)

  76.     {

  77.       using (

  78.         ResultBuffer resBuf = ent.GetXDataForApplication(appName))

  79.       {

  80.         return NewFromResBuf(resBuf);

  81.       }

  82.     }



  83.     public ResultBuffer SaveToResBuf()

  84.     {

  85.       BinaryFormatter bf = new BinaryFormatter();

  86.       MemoryStream ms = new MemoryStream();

  87.       bf.Serialize(ms, this);

  88.       ms.Position = 0;



  89.       ResultBuffer resBuf = MyUtil.StreamToResBuf(ms, appName);



  90.       return resBuf;

  91.     }



  92.     public void SaveToEntity(Entity ent)

  93.     {

  94.       // Make sure application name is registered

  95.       // If we were to save the ResultBuffer to an Xrecord.Data,

  96.       // then we would not need to have a registered application name



  97.       Transaction tr =

  98.         ent.Database.TransactionManager.TopTransaction;



  99.       RegAppTable regTable =

  100.         (RegAppTable)tr.GetObject(

  101.           ent.Database.RegAppTableId, OpenMode.ForWrite);

  102.       if (!regTable.Has(MyClass.appName))

  103.       {

  104.         RegAppTableRecord app = new RegAppTableRecord();

  105.         app.Name = MyClass.appName;

  106.         regTable.Add(app);

  107.         tr.AddNewlyCreatedDBObject(app, true);

  108.       }



  109.       using (ResultBuffer resBuf = SaveToResBuf())

  110.       {

  111.         ent.XData = resBuf;

  112.       }

  113.     }



  114.     [SecurityPermission(SecurityAction.LinkDemand,

  115.        Flags = SecurityPermissionFlag.SerializationFormatter)]

  116.     public abstract void GetObjectData(

  117.       SerializationInfo info, StreamingContext context);

  118.   }



  119.   [Serializable]

  120.   public class MyClass : MyBaseClass

  121.   {

  122.     public string myString;

  123.     public double myDouble;



  124.     public MyClass()

  125.     {

  126.     }



  127.     protected MyClass(

  128.       SerializationInfo info, StreamingContext context)

  129.     {

  130.       if (info == null)

  131.         throw new System.ArgumentNullException("info");



  132.       myString = (string)info.GetValue("MyString", typeof(string));

  133.       myDouble = (double)info.GetValue("MyDouble", typeof(double));

  134.     }



  135.     [SecurityPermission(SecurityAction.LinkDemand,

  136.        Flags = SecurityPermissionFlag.SerializationFormatter)]

  137.     public override void GetObjectData(

  138.       SerializationInfo info, StreamingContext context)

  139.     {

  140.       info.AddValue("MyString", myString);

  141.       info.AddValue("MyDouble", myDouble);

  142.     }



  143.     // Just for testing purposes



  144.     public override string ToString()

  145.     {

  146.       return base.ToString() + "," +

  147.         myString + "," + myDouble.ToString();

  148.     }

  149.   }



  150.   public class Commands

  151.   {

  152.     [CommandMethod("SaveClassToEntityXData")]

  153.     static public void SaveClassToEntityXData()

  154.     {

  155.       Database db = acApp.DocumentManager.MdiActiveDocument.Database;

  156.       Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;



  157.       PromptEntityResult per =

  158.         ed.GetEntity("Select entity to save class to:\n");

  159.       if (per.Status != PromptStatus.OK)

  160.         return;



  161.       // Create an object



  162.       MyClass mc = new MyClass();

  163.       mc.myDouble = 1.2345;

  164.       mc.myString = "Some text";



  165.       // Save it to the document



  166.       using (

  167.         Transaction tr = db.TransactionManager.StartTransaction())

  168.       {

  169.         Entity ent =

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



  171.         mc.SaveToEntity(ent);



  172.         tr.Commit();

  173.       }



  174.       // Write some info about the results



  175.       ed.WriteMessage(

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

  177.     }



  178.     [CommandMethod("GetClassFromEntityXData")]

  179.     static public void GetClassFromEntityXData()

  180.     {

  181.       Database db = acApp.DocumentManager.MdiActiveDocument.Database;

  182.       Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;



  183.       PromptEntityResult per =

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

  185.       if (per.Status != PromptStatus.OK)

  186.         return;



  187.       // Get back the class



  188.       using (

  189.         Transaction tr = db.TransactionManager.StartTransaction())

  190.       {

  191.         Entity ent =

  192.           (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);



  193.         MyClass mc = (MyClass)MyClass.NewFromEntity(ent);



  194.         // Write some info about the results



  195.         ed.WriteMessage(

  196.           "Content of MyClass we deserialized:\n {0} \n",

  197.           mc.ToString());



  198.         tr.Commit();

  199.       }

  200.     }

  201.   }



  202. }
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-12-18 23:55 , Processed in 0.331640 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表