C# GetData()是否返回MemoryStream类型的对象?

C# GetData()是否返回MemoryStream类型的对象?,c#,winforms,clipboard,C#,Winforms,Clipboard,我不知道为什么GetData()方法需要类型为的参数,我认为类型是指定对象应该属于哪个类/类型。 我有一个名为GraphicsPathWrap的结构,通过实现ISerializable使其可序列化。我尝试了以下复制功能: private void Copy(GraphicsPathWrap gpw){ DataObject obj = new DataObject(); obj.SetData(typeof(GraphicsPathWrap), gpw); Clipboard.Set

我不知道为什么GetData()方法需要类型为的参数,我认为类型是指定对象应该属于哪个类/类型。 我有一个名为GraphicsPathWrap的结构,通过实现ISerializable使其可序列化。我尝试了以下复制功能:

private void Copy(GraphicsPathWrap gpw){
  DataObject obj = new DataObject();
  obj.SetData(typeof(GraphicsPathWrap), gpw);
  Clipboard.SetDataObject(obj);
}
private GraphicsPathWrap Paste()
{
  return (GraphicsPathWrap)Clipboard.GetDataObject().GetData(typeof   (GraphicsPathWrap));
}
然后尝试了以下粘贴功能:

private void Copy(GraphicsPathWrap gpw){
  DataObject obj = new DataObject();
  obj.SetData(typeof(GraphicsPathWrap), gpw);
  Clipboard.SetDataObject(obj);
}
private GraphicsPathWrap Paste()
{
  return (GraphicsPathWrap)Clipboard.GetDataObject().GetData(typeof   (GraphicsPathWrap));
}
它应该可以工作,但GetData(…)返回MemoryStream类型的对象,并引发InvalidCastException。我不明白为什么这是一种记忆流。我想它应该可以铸造成一个形状? 我可以通过使用BinaryFormatter来反序列化MemoryStream来解决这个问题,但是当剪贴板不能为我做所有事情时,这太可笑了


谢谢

Clipboard.SetDataObject(object data)方法名有点误导,因为它不是专门要求一个DataObject作为参数,而是一个必须可序列化的对象

您可以尝试直接通过gpw,如下所示:

private void Copy(GraphicsPathWrap gpw){
  Clipboard.SetDataObject(gpw);
}
    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }

        object o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
        return (SerializedClipboardFragment)o;
    }
如果GraphicsPathWrap是可序列化的,它应该可以工作

编辑:在我自己测试之后,结果表明该方法是双向的,要么直接传递可序列化对象,要么将其封装在DataObject中。我通过检查特定剪贴板方法的.Net源代码确认了这一点,在那里我发现:

if (data is DataObject) 
{
      dataObject = (DataObject)data; 
}

因此,正如Ramesh在另一个答案中所说,您可能需要检查对象是否正确设置为可序列化。

剪贴板。SetDataObject(对象数据)方法名称有点误导,因为它不是专门要求DataObject作为参数,而只是一个必须可序列化的对象

您可以尝试直接通过gpw,如下所示:

private void Copy(GraphicsPathWrap gpw){
  Clipboard.SetDataObject(gpw);
}
    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }

        object o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
        return (SerializedClipboardFragment)o;
    }
如果GraphicsPathWrap是可序列化的,它应该可以工作

编辑:在我自己测试之后,结果表明该方法是双向的,要么直接传递可序列化对象,要么将其封装在DataObject中。我通过检查特定剪贴板方法的.Net源代码确认了这一点,在那里我发现:

if (data is DataObject) 
{
      dataObject = (DataObject)data; 
}

因此,正如Ramesh在另一个答案中所说,您可能需要检查您的对象是否正确设置为可序列化。

编辑:我完全模拟了您的情况,问题是,当您实现ISerializable接口但未正确反序列化它时,您说的是MemoryStream

GetData()在以下情况下返回内存流:

      [Serializable]
        public struct GraphicsPathWrap : ISerializable
        {
            private static string myValue = "This is the value of the class";             

            // Creates a property to retrieve or set the value. 
            public string MyObjectValue
            {
                get
                {
                    return myValue;
                }
                set
                {
                    myValue = value;
                }
            }

            #region ISerializable Members

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {

            }

            #endregion
        } 
然后,当GetData()给出正确的对象类型时,我正确地实现了序列化\反序列化

[Serializable]
        public struct GraphicsPathWrap : ISerializable
        {
            private static string myValue = "This is the value of the class";

            public GraphicsPathWrap(SerializationInfo info, StreamingContext ctxt)  // Deserialization Constructor
            {
                myValue = (string)info.GetValue("MyValue", typeof(string));
            }

            // Creates a property to retrieve or set the value. 
            public string MyObjectValue
            {
                get
                {
                    return myValue;
                }
                set
                {
                    myValue = value;
                }
            }

            #region ISerializable Members

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                info.AddValue("MyValue", myValue); // Serialize the value
            }

            #endregion
        }

我希望上面的答案能帮助您编辑:我完全模拟了您的情况,问题是当您实现ISerializable接口但没有正确反序列化它时,我说的是MemoryStream

[DataObject(true)]
    public class EmployeeDAL
    {
        [DataObjectMethod(DataObjectMethodType.Update, true)]
        public int UpdateEmployeeSalary(int percentage, int deptid, int posid)
        {
            OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            OracleCommand cmd = new OracleCommand("GIVE_RAISE_SP", con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("PV_PERCENTAGE_RAISE_I", OracleType.Int32).Value = percentage;
            cmd.Parameters.AddWithValue("PV_POSITIONID_I", OracleType.Int32).Value = posid;
stac            cmd.Parameters.AddWithValue("PV_DEPTID_I", OracleType.Int32).Value = deptid;
            cmd.Parameters.AddWithValue("PV_NUM_EMPLOYEES_O", OracleType.Int32).Direction = ParameterDirection.Output;

            OracleDataAdapter da = new OracleDataAdapter(cmd);

            try
            {
                con.Open();
                da.UpdateCommand = cmd;
                cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {

            }
            finally
            {
                con.Close();
            }

            return Convert.ToInt32(cmd.Parameters["PV_NUM_EMPLOYEES_O"].Value);
        }
GetData()在以下情况下返回内存流:

      [Serializable]
        public struct GraphicsPathWrap : ISerializable
        {
            private static string myValue = "This is the value of the class";             

            // Creates a property to retrieve or set the value. 
            public string MyObjectValue
            {
                get
                {
                    return myValue;
                }
                set
                {
                    myValue = value;
                }
            }

            #region ISerializable Members

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {

            }

            #endregion
        } 
然后,当GetData()给出正确的对象类型时,我正确地实现了序列化\反序列化

[Serializable]
        public struct GraphicsPathWrap : ISerializable
        {
            private static string myValue = "This is the value of the class";

            public GraphicsPathWrap(SerializationInfo info, StreamingContext ctxt)  // Deserialization Constructor
            {
                myValue = (string)info.GetValue("MyValue", typeof(string));
            }

            // Creates a property to retrieve or set the value. 
            public string MyObjectValue
            {
                get
                {
                    return myValue;
                }
                set
                {
                    myValue = value;
                }
            }

            #region ISerializable Members

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                info.AddValue("MyValue", myValue); // Serialize the value
            }

            #endregion
        }

我希望上面的答案能帮助您

我正在使用
剪贴板。GetData
与类型为
SerializedClipboardFragment
的对象—这是我自己的一种类型,一个类,我用
[Serializable()]属性标记了它:

[DataObject(true)]
    public class EmployeeDAL
    {
        [DataObjectMethod(DataObjectMethodType.Update, true)]
        public int UpdateEmployeeSalary(int percentage, int deptid, int posid)
        {
            OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            OracleCommand cmd = new OracleCommand("GIVE_RAISE_SP", con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("PV_PERCENTAGE_RAISE_I", OracleType.Int32).Value = percentage;
            cmd.Parameters.AddWithValue("PV_POSITIONID_I", OracleType.Int32).Value = posid;
stac            cmd.Parameters.AddWithValue("PV_DEPTID_I", OracleType.Int32).Value = deptid;
            cmd.Parameters.AddWithValue("PV_NUM_EMPLOYEES_O", OracleType.Int32).Direction = ParameterDirection.Output;

            OracleDataAdapter da = new OracleDataAdapter(cmd);

            try
            {
                con.Open();
                da.UpdateCommand = cmd;
                cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {

            }
            finally
            {
                con.Close();
            }

            return Convert.ToInt32(cmd.Parameters["PV_NUM_EMPLOYEES_O"].Value);
        }
[Serializable()]
public class SerializedClipboardFragment
{
    readonly string[] m_ancestors;
    readonly string m_fragment;
    readonly int m_numberOfNodes;
    readonly bool m_isInsertingBlock;
    readonly bool m_isInsertingTable;

    public SerializedClipboardFragment(
        string[] ancestors,
        string fragment,
        int numberOfNodes,
        bool isInsertingBlock,
        bool isInsertingTable
        )
    {
        m_ancestors = ancestors;
        m_fragment = fragment;
        m_numberOfNodes = numberOfNodes;
        m_isInsertingBlock = isInsertingBlock;
        m_isInsertingTable = isInsertingTable;
    }

    internal static DataFormats.Format s_format;
    static SerializedClipboardFragment()
    {
        s_format = DataFormats.GetFormat(typeof(SerializedClipboardFragment).FullName);
    }

    ... etc -- various get-only properties ...
}
我从剪贴板获取此数据的代码如下所示:

private void Copy(GraphicsPathWrap gpw){
  Clipboard.SetDataObject(gpw);
}
    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }

        object o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
        return (SerializedClipboardFragment)o;
    }
当我测试这个时,我发现它通常是有效的

但在我的自动回归测试中,它有时会失败,在设置数据后,我会立即尝试从剪贴板获取数据。。。e、 g.在连续30次成功设置后,可能会失败,然后进行尝试

如果失败,则如您所述,即对象是
内存流

请注意,它不应该失败,因为最近返回了
true

我意识到只有一个系统剪贴板;当运行这个测试时,我的手离开了键盘,在这个过程中我并没有试图干扰剪贴板

无论如何,如果我按如下方式编写代码,问题似乎就消失了:

    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }
        // sometimes return MemoryStream object instead under automated-testing
        // possibly a timing problem
        object o = null;
        for (int i = 0; i < 10; ++i)
        {
            o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
            if (o is SerializedClipboardFragment)
                return (SerializedClipboardFragment)o;
            System.Threading.Thread.Sleep(100);
        }
        return (SerializedClipboardFragment)o;
    }
公共静态SerializedClipboardFragment getSerializedFragment()
{
if(!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
{
返回null;
}
//有时在自动测试下返回MemoryStream对象
//可能是时间问题
对象o=null;
对于(int i=0;i<10;++i)
{
o=Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
if(o是序列化的LipboardFragment)
返回(序列化的dclipboardfragment)o;
系统线程线程睡眠(100);
}
返回(序列化的dclipboardfragment)o;
}

因此,除非我弄错了,否则这可能是一些令人反感的计时错误,与在剪贴板中存储自定义数据类型相关。

我正在使用
剪贴板。GetData
与类型为
SerializedClipboardFragment
的对象一起使用——这是我自己的一种类型,一个类,我用
[Serializable()]属性标记了它:

[Serializable()]
public class SerializedClipboardFragment
{
    readonly string[] m_ancestors;
    readonly string m_fragment;
    readonly int m_numberOfNodes;
    readonly bool m_isInsertingBlock;
    readonly bool m_isInsertingTable;

    public SerializedClipboardFragment(
        string[] ancestors,
        string fragment,
        int numberOfNodes,
        bool isInsertingBlock,
        bool isInsertingTable
        )
    {
        m_ancestors = ancestors;
        m_fragment = fragment;
        m_numberOfNodes = numberOfNodes;
        m_isInsertingBlock = isInsertingBlock;
        m_isInsertingTable = isInsertingTable;
    }

    internal static DataFormats.Format s_format;
    static SerializedClipboardFragment()
    {
        s_format = DataFormats.GetFormat(typeof(SerializedClipboardFragment).FullName);
    }

    ... etc -- various get-only properties ...
}
我从剪贴板获取此数据的代码如下所示:

private void Copy(GraphicsPathWrap gpw){
  Clipboard.SetDataObject(gpw);
}
    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }

        object o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
        return (SerializedClipboardFragment)o;
    }
当我测试这个时,我发现它通常是有效的

但在我的自动回归测试中,它有时会失败,在设置数据后,我会立即尝试从剪贴板获取数据。。。e、 g.在连续30次成功设置后,可能会失败,然后进行尝试

如果失败,则如您所述,即对象是
内存流

请注意,它不应该失败,因为最近返回了
true

我意识到只有一个系统剪贴板;当运行这个测试时,我的手离开了键盘,在这个过程中我并没有试图干扰剪贴板

无论如何,如果我按如下方式编写代码,问题似乎就消失了:

    public static SerializedClipboardFragment getSerializedFragment()
    {
        if (!Clipboard.ContainsData(SerializedClipboardFragment.s_format.Name))
        {
            return null;
        }
        // sometimes return MemoryStream object instead under automated-testing
        // possibly a timing problem
        object o = null;
        for (int i = 0; i < 10; ++i)
        {
            o = Clipboard.GetData(SerializedClipboardFragment.s_format.Name);
            if (o is SerializedClipboardFragment)
                return (SerializedClipboardFragment)o;
            System.Threading.Thread.Sleep(100);
        }
        return (SerializedClipboardFragment)o;
    }
公共静态SerializedClipboardFragment getSerializedFragment()
{
如果(!Clipboard.C