4

C# でクリップボード スタックを作成しようとしています。クリップボードのデータはSystem.Windows.Forms.DataObjectオブジェクトに保存されます。IDataObject各クリップボード エントリ ( ) をジェネリック リストに直接保存したかったのです。ビットマップ (と思われる) の保存方法のため、リストに追加する前に、まずディープ コピーを実行する必要があると考えています。

バイナリ シリアライゼーション (以下を参照) を使用してディープ コピーを作成しようとしましたがSystem.Windows.Forms.DataObject、シリアライズ可能としてマークされていないため、シリアライゼーション ステップは失敗します。何か案は?

public IDataObject GetClipboardData()
{
    MemoryStream memoryStream = new MemoryStream();
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(memoryStream, Clipboard.GetDataObject());
    memoryStream.Position = 0;
    return (IDataObject) binaryFormatter.Deserialize(memoryStream);
}
4

3 に答える 3

3

別の質問のために以下のコードを書きましたが、このシナリオで役立つかもしれません。

    public static class GhettoSerializer
    {
            // you could make this a factory method if your type
            // has a constructor that appeals to you (i.e. default 
            // parameterless constructor)
            public static void Initialize<T>(T instance, IDictionary<string, object> values)
            {
                    var props = typeof(T).GetProperties();

                    // my approach does nothing to handle rare properties with array indexers
                    var matches = props.Join(
                            values,
                            pi => pi.Name,
                            kvp => kvp.Key,
                            (property, kvp) =>
                                    new {
                                            Set = new Action<object,object,object[]>(property.SetValue), 
                                            kvp.Value
                                    }
                    );

                    foreach (var match in matches)
                            match.Set(instance, match.Value, null);
            }
            public static IDictionary<string, object> Serialize<T>(T instance)
            {
                    var props = typeof(T).GetProperties();

                    var ret = new Dictionary<string, object>();

                    foreach (var property in props)
                    {
                            if (!property.CanWrite || !property.CanRead)
                                    continue;
                            ret.Add(property.Name, property.GetValue(instance, null));
                    }

                    return ret;
            }
    }

ただし、これが問題の最終的な解決策になるとは思いませんが、開始する場所になる可能性があります。

于 2008-10-14T17:09:38.450 に答える
0

Serializable のドックを調べて、シリアライゼーション ヘルパーに関する情報を見つけてください。.net フレームワークと統合する独自のシリアル化コードでビットマップをラップできます。

于 2009-01-05T04:56:01.467 に答える
0

私の回答のコピー: .net の DataContract 属性と Serializable 属性の違い

上記の質問は次で終わりますが、私の答えはここよりもはるかに適しています。

「... それとも、ディープクローンを作成する別の方法ですか?」

リフレクションを介してオブジェクト構造を検査したことがあります。

ちょっとした作業で、ディープ コピー用の同様の方法を構築できます。基本的に、循環参照を検出するには Dictionary を使用する再帰的なメソッドが必要です。メソッド内では、次のようにすべてのフィールドを検査します。

private void InspectRecursively(object input,
    Dictionary<object, bool> processedObjects)
{
  if ((input != null) && !processedObjects.ContainsKey(input))
  {
    processedObjects.Add(input, true);

    List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
        BindingFlags.Public | BindingFlags.NonPublic );
    foreach (FieldInfo field in fields)
    {
      object nextInput = field.GetValue(input);

      if (nextInput is System.Collections.IEnumerable)
      {
        System.Collections.IEnumerator enumerator = (nextInput as
            System.Collections.IEnumerable).GetEnumerator();

        while (enumerator.MoveNext())
        {
          InspectRecursively(enumerator.Current, processedObjects);
        }
      }
      else
      {
        InspectRecursively(nextInput, processedObjects);
      }
    }
  }
}

それを機能させるには、出力オブジェクトを追加する必要がありSystem.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type)、各フィールドの値の最も浅いコピー (参照をコピーしなくても) を作成するようなものを追加する必要があります。最後に、各フィールドを次のように設定できますfield.SetValue(input, output)

ただし、この実装は登録されたイベントハンドラーをサポートしていません。これは、逆シリアル化でもサポートされていません。さらに、クラスのコンストラクターがすべてのフィールドを設定する以外に何かを初期化する必要がある場合、階層内の各オブジェクトは壊れます。[OnDeserialized]クラスにそれぞれの実装がある場合、最後のポイントはシリアライゼーションでのみ機能しISerializableます。

于 2013-11-07T13:18:15.303 に答える