Reading old clipboard data in new program version in C#

对着背影说爱祢 提交于 2019-12-11 04:38:21

问题


We have an old program version where we put a serializable class into the clipboard. For this example lets say something like this:

namespace ClipboardLibrary
{
    [Serializable]
    public class ClipboardData
    {
        public string Content { get; set; }
    }
}

Now in the new version to keep it for this example simple the class looks the same except the namespace was changed like so:

namespace ClipboardLibrary.OtherNamespace
{
    [Serializable]
    public class ClipboardData
    {
        public string Content { get; set; }
    }
}

When I copy now from the old version - where it is done by simply call SetData(someKey, clipboardData) and try to get the deserialize the data via Clipboard.GetData(someKey) I get a serialization exception:

System.Runtime.Serialization.SerializationException was unhandled
  HResult=-2146233076
  Message=Der für die Deserialisierung benötigte Typ "ClipboardLibrary.ClipboardData" kann nicht geladen werden.
  Source=mscorlib
  StackTrace:
      bei System.Runtime.Serialization.ObjectManager.DoFixups()
      bei System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
      bei System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
      bei System.Windows.DataObject.OleConverter.ReadObjectFromHandle(IntPtr handle)
      bei System.Windows.DataObject.OleConverter.GetDataFromHGLOBAL(String format, IntPtr hglobal)
      bei System.Windows.DataObject.OleConverter.GetDataFromOleHGLOBAL(String format, DVASPECT aspect, Int32 index)
      bei System.Windows.DataObject.OleConverter.GetDataFromBoundOleDataObject(String format, DVASPECT aspect, Int32 index)
      bei System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)
      bei System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)
      bei System.Windows.DataObject.GetData(String format, Boolean autoConvert)
      bei System.Windows.Clipboard.GetDataInternal(String format)
      bei System.Windows.Clipboard.GetData(String format)
      bei CopyPaste.MainWindow.Button_Click_1(Object sender, RoutedEventArgs e) in c:\Users\twilker\Documents\Visual Studio 2013\Projects\CopyPaste\CopyPaste\MainWindow.xaml.cs:Zeile 42.
      ...

I am sorry of the German text here. What it says is that the type ClipboardLibrary.ClipboardData could not be found, which makes obvious sense.

Is there a possibility to retrieve the data anyway somehow?


回答1:


You can reference old assembly in the new one and obtain ClipboardLibrary.ClipboardData Type via deserialization without exceptions. And implement in the new assembly convertor from ClipboardLibrary.ClipboardData to ClipboardLibrary.OtherNamespace.ClipboardData.




回答2:


I'm not sure how to make it work when interacting with Clipboard. Because deserialization isn't with our control(AFAIK).

If you're directly dealing with BinaryFormatter you can create a custom SerializationBinder as below.

public class CustomSerializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        if (typeName == "ClipboardLibrary.ClipboardData")
        {
            return typeof(ClipboardLibrary.OtherNamespace.ClipboardData);
        }
        return Type.GetType(String.Format("{0}, {1}",
                typeName, assemblyName));
    }
}

private ClipboardLibrary.OtherNamespace.ClipboardData DeSerialize(Stream stream)
{
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Binder = new CustomSerializationBinder();
    return (ClipboardLibrary.OtherNamespace.ClipboardData)formatter.Deserialize(stream);
}

With that, we're asking the BinaryFormatter to load ClipboardLibrary.OtherNamespace.ClipboardData type when it asks for ClipboardLibrary.ClipboardData. Sort of type redirection.




回答3:


Probably the easiest solution would be to define a class in the old namespace along the one in the new namespace and then after it deserializes successfully map the old one to the new one.



来源:https://stackoverflow.com/questions/29922516/reading-old-clipboard-data-in-new-program-version-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!