C# 在Autocad.Net WCF插件中保留ObjectId引用
有一个.Net Autocad插件,其中使用WCF服务调用方法 在Autocad外部的另一个进程上。Autocad图元包装在自定义类中并通过WCF传递。调用返回后,插件需要将结果写回Autocad数据库 问题是:需要ObjectId来获取对象并写回结果;WCF序列化数据,ObjectId不可序列化。所以我无法访问该对象C# 在Autocad.Net WCF插件中保留ObjectId引用,c#,wcf,serialization,autocad,autocad-plugin,C#,Wcf,Serialization,Autocad,Autocad Plugin,有一个.Net Autocad插件,其中使用WCF服务调用方法 在Autocad外部的另一个进程上。Autocad图元包装在自定义类中并通过WCF传递。调用返回后,插件需要将结果写回Autocad数据库 问题是:需要ObjectId来获取对象并写回结果;WCF序列化数据,ObjectId不可序列化。所以我无法访问该对象 是否有解决方法/解决方案?您必须序列化ObjectId的值句柄,因为它不可序列化: [Serializable] public class TobeSerialized {
是否有解决方法/解决方案?您必须序列化
ObjectId
的值句柄,因为它不可序列化:
[Serializable]
public class TobeSerialized
{
private long idHandleValue;
[NonSerialized]
private ObjectId id;
public TobeSerialized()
{
this.idHandleValue = id.Handle.Value;
}
public ObjectId GetObjectId(Database database, long handleValue)
{
Handle handle = new Handle(handleValue);
ObjectId id = database.GetObjectId(false, handle, 0);
return id;
}
}
然后,当您反序列化您的
类对象时
您将能够通过调用方法GetObjectId(数据库,long handleValue)
来获取objectId
,因为它是不可序列化的:
[Serializable]
public class TobeSerialized
{
private long idHandleValue;
[NonSerialized]
private ObjectId id;
public TobeSerialized()
{
this.idHandleValue = id.Handle.Value;
}
public ObjectId GetObjectId(Database database, long handleValue)
{
Handle handle = new Handle(handleValue);
ObjectId id = database.GetObjectId(false, handle, 0);
return id;
}
}
然后,当您反序列化您的
类对象时,您将能够通过调用方法GetObjectId(数据库,long handleValue)
来获取objectId
,您可以使用属性objectId.OldIdPtr
,它是一个IntPtr
(可序列化)。要恢复您的ObjectId
,只需执行以下操作:
var id = new ObjectId(oldIdPtr);
这比使用句柄(需要查找)更直接。您可以使用属性ObjectId.OldIdPtr
,它是一个IntPtr
(可序列化)。要恢复您的ObjectId
,只需执行以下操作:
var id = new ObjectId(oldIdPtr);
这是一种比使用句柄(需要查找)更直接的方法。对于每个实体,您可以直接获得句柄,而无需中介(objectId)。
使用Entity.Handle属性。
《autocad指南》的进一步介绍
数据库对象中包含的每个对象都分配了几个唯一的ID。访问对象的独特方式有:
实体句柄
目标
实例指针
最常用的方法是通过对象Id访问对象。如果您的项目同时使用COM互操作和托管的.NET API,则对象Id可以正常工作。如果创建自定义AutoLISP函数,则可能需要使用实体句柄。
控制柄在AutoCAD任务之间保持不变,因此,如果需要将图形信息输出到外部文件(以后可能需要使用该文件更新图形),则控制柄是访问对象的最佳方式。数据库中对象的ObjectId仅在数据库加载到内存时存在。关闭数据库后,分配给对象的对象ID将不再存在,并且在下次打开数据库时可能会有所不同。对于每个实体,您可以直接获得句柄,而无需中介(objectId)。
使用Entity.Handle属性。
《autocad指南》的进一步介绍
数据库对象中包含的每个对象都分配了几个唯一的ID。访问对象的独特方式有:
实体句柄
目标
实例指针
最常用的方法是通过对象Id访问对象。如果您的项目同时使用COM互操作和托管的.NET API,则对象Id可以正常工作。如果创建自定义AutoLISP函数,则可能需要使用实体句柄。
控制柄在AutoCAD任务之间保持不变,因此,如果需要将图形信息输出到外部文件(以后可能需要使用该文件更新图形),则控制柄是访问对象的最佳方式。数据库中对象的ObjectId仅在数据库加载到内存时存在。一旦数据库关闭,分配给对象的对象ID将不再存在,并且在下次打开数据库时可能会有所不同。感谢Zimer的回答。我知道这个解决办法。但我关心的是GetObjectId在大量数据上的性能。这个方法实际上是做什么的?它是创建新的ObjectId还是在数据库中查找它?@ali:Zimmer是对的。事实上,我看不出这个插件是如何序列化实体的。它们也包含ObjectId。更不用说它们没有标记为可序列化。但是,它们确实实现了MarshalByRefObject,这意味着它们可以通过远程处理发送,但不能通过WCF发送(据我所知)。我的猜测是,他们要么在使用一些远程处理魔法,要么在使用实体属性的POCO表示。如果是后者,那么他们就是在做齐默的建议。@ali:Btw。。。句柄是文档的持久化ID。ObjectId是会话的临时ID。因此,它实际上是从该会话的图形数据库中检索该对象的会话注册ObjectId。代码还必须考虑句柄是十六进制值这一事实,所以使用这个。。。ObjectId oid=currentDB.GetObjectId(false,新句柄(Convert.ToInt64(句柄,16)),0)@ali:根据Autodesk ObjectARX的文档,此方法返回对象的objectId,该对象的句柄值包含在objHandle中,因此我们可以说它将在数据库中查找该对象。@Zimer:很抱歉我对代码示例的第二条评论。不知什么原因,我以为我看到你在用绳子。我忽略了一个事实,你一直在通过它。谢谢齐默的回答。我知道这个解决办法。但我关心的是GetObjectId在大量数据上的性能。这个方法实际上是做什么的?它是创建新的ObjectId还是在数据库中查找它?@ali:Zimmer是对的。事实上,我看不出这个插件是如何序列化实体的。它们也包含ObjectId。更不用说它们没有标记为可序列化。但是,它们确实实现了MarshalByRefObject,这意味着它们可以通过远程处理发送,但不能通过WCF发送(据我所知)。我的猜测是,他们要么在使用一些远程处理魔法,要么在使用实体属性的POCO表示。如果是后者,那么他们就是在做齐默的建议。@ali:Btw。。。句柄是文档的持久化ID。ObjectId是具有