WinForms C#中自定义对象类型的跨进程拖放

Posted

技术标签:

【中文标题】WinForms C#中自定义对象类型的跨进程拖放【英文标题】:Cross-Process Drag and Drop of custom object type in WinForms C# 【发布时间】:2011-01-07 13:14:54 【问题描述】:

This question 与我感兴趣的内容接近,但并不完全。

我有一个用 C# 编写的 .NET WinForms 应用程序。我有一个ListView 控件,它显示一个 C# 对象数组。我已经将它连接起来,以便您可以将这些列表视图项拖放到同一应用程序中的不同表单,并且它会正确地将对象数组(类型 Session)传递给该其他表单的放置处理程序。

但是,我现在想在运行多个应用程序实例的地方支持跨进程拖放。这显示它会起作用(例如GetDataPresent 成功),但当我实际尝试检索数据时最终会引发异常——无法将object[] 转换为Session[]

if (e.Data.GetDataPresent("Fiddler.Session[]"))

   Session[] oDroppedSessions;
   try
   
      oDroppedSessions = (Session[])e.Data.GetData("Fiddler.Session[]");
   
   catch (Exception eX)
     // reaches here 
   

任何人都知道我是否必须为我的对象实现ISerializable 以使其工作?通常情况下,我会简单地尝试一下,但是为这个类实现ISerializable 将非常重要,而且我担心这样做可能会产生奇怪的副作用。


更新:实现ISerializable 无济于事——该方法永远不会被调用。同样,将Serializable 属性添加到类中完全没有影响。还有其他想法吗?

【问题讨论】:

添加一行'Console.WriteLine(string.Format("异常捕获。详细信息是0", eX.ToString()));'在 catch 块中。消息是什么? "无法将 object[] 转换为 Session[]" 【参考方案1】:

您正在跨越进程边界,对象引用在另一个进程中无效。 DataObject 类支持序列化对象以使它们穿过墙壁,它使用 BinaryFormatter。所以,是的,您需要将 [Serializable] 属性应用于您的类,并确保您的对象可以正确反序列化。

【讨论】:

是的,这就是我害怕的。如果我实现 ISerializable 是否要引入性能回归,知道吗?这个对象的二进制序列化可能是数百 KB。 当您发现时请告诉我们。 嗯...实现 ISerializable 并没有帮助——该方法永远不会被调用。同样,将 Serializable 属性添加到类中完全没有影响。还有其他想法吗? 使用DataFormat.Serializable触发序列化代码。 事实证明,如果我同时添加 ISerializable 和 Serializable 属性,并在 ISerializable 实现中放置一个 MessageBox,然后我看到它被命中了。如果我只是让我的 ISerializable 实现发出一个 Not Yet Implemented 异常,那么该异常会在途中的某个地方被吃掉,我仍然会得到旧的“无法将对象 [] 转换为 Session []”异常。所以,现在我只需要编写一堆代码来使我的 ISerializable 实现工作。感谢您的帮助!【参考方案2】:

好吧,这是一个镜头,而不是使用整个会话数组,尝试像这样单独进行......

会话[] oDroppedSessions; 尝试 if (e.Data.GetData("Fiddler.Session[]") != null) object[] objs = e.Data.GetData("Fiddler.Session[]"); if (objs != null && objs.Length > 1) oDroppedSessions = 新会话[objs.Length]; int nIndex = 0; foreach(objs 中的对象 obj) if (obj 是会话) oDroppedSessions[nIndex] = (Session)obj; n索引++; 捕获(异常 eX) // 到达这里

值得一试,除了因为我不完全理解 Session 部分而在脚上射击自己,尝试一下......

希望这会有所帮助, 最好的祝福, 汤姆。

【讨论】:

【参考方案3】:

您可以使用“as”进行强制转换,这将避免异常(如果强制转换失败,“as”将返回“null”而不抛出异常) - 但我认为这不会解决您的问题(它只会避免实际的异常),因为我同意您可能必须使您的类可序列化。您可以通过注释掉更难使其工作的字段来测试您的假设 - 只是现在来测试它。

【讨论】:

-1:将InvalidCastException 换成NullReferenceException 会丢失信息。 as 关键字是很好的,如果你预计一个演员 可能 失败。否则,它很糟糕,而且我已经看到它被过度使用了。

以上是关于WinForms C#中自定义对象类型的跨进程拖放的主要内容,如果未能解决你的问题,请参考以下文章

WinForms中常见的“拖放”图标如何实现

拖放DataGrid中下降,拖动过程中自定义光标不工作

Winforms -> 可视化拖放项目

WCF c#中自定义类的传输问题

C# WinForms DragEnter 从不触发

C# 拖放 - 使用基类的 e.Data.GetData