4

オブジェクトのシリアル化に問題があり、問題を特定のケースに絞り込みました (以下のコードを参照)。次のエラーが発生しました。

エラー 1 Resx ファイルが無効です。.RESX ファイルで使用されているタイプ Serialisation.Harness.Blob、Serialisation、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null を読み込めませんでした。必要な参照がプロジェクトに追加されていることを確認してください。行 129、位置 5. ...

ここで本当に奇妙なことは、Visual Studio を再起動するとエラーが消えてコードが機能するようになるが、ランダムな数のビルド (コードが変更されていない間) の後、再び壊れることです。

私が間違っている/見逃していることがわかりますか?

よろしくお願いします。

めと

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design; using System.ComponentModel.Design;

namespace Serialisation.Harness
{    

    [Serializable]
    public class Blob
    {
        public Blob()
        {
        }
    }

    [Serializable]
    public class Basic
    {

        private List<Blob> blobs;
        public List<Blob> Blobs
        {
            get { return blobs; }
            set { this.blobs= value; }
        }

        public Basic()
        {
            basics = new List<Blob>();
        }

    }

    public class BasicComponent : Component
    {

        private Basic basic = new Basic();

        private IContainer components = new Container();

        public List<Blob> Blobs
        {
            get { return basic.Blobs; }
            set { basic.Blobs= value; }
        }

        public BasicComponent(IContainer container)
        {
            container.Add(this);
        }

    }

}
4

1 に答える 1

6

まず、このSerializable属性はデザイナーのシリアル化には使用されません。オブジェクトをシリアル化するとき、デザイナーはリソース ファイルをデザイナー コードに書き込む方法がわからない場合、リソース ファイルにシリアル化します。これにより、オブジェクト タイプのデフォルト コンストラクターの を使用して blob として resx に書き出されInstanceDescriptorます (これにより、含めたいプロパティ値も失われます)。Blobsこれは、デザイナーが一般的なリストを適切にシリアル化しないため、プロパティで起こっていることです(ただし、配列をシリアル化する方法は知っています)。

これらの永続化されたオブジェクト内の情報を保持するにはTypeConverter、別のコンストラクターを指定するを作成する必要がありますInstanceDescriptor(プロパティなどのプロパティを記述するために実際に何らかの状態を取るコンストラクターBlobs)。たとえば、を受け取るBasicComponent型にコンストラクターを追加した場合、そのコンストラクターに をIEnumerable<Blob>取得して、 s のInstanceDescriptor配列を渡すことができBlobます (コンストラクターでその周りに新しい を作成しますList<Blob>)。デザイナーはto コードを永続InstanceDescriptor化する方法と、配列をコードに永続化する方法を知っているため、resx ではなくこれをデザイナー コードに追加します。

インスタンスを記述するために使用されるコードを指定するために を実装することもできCodeDomSerializerます。これにより、デザイナーはオブジェクトを resx ではなくデザイナー コードに保存するために使用できます。

型コンバーター

型コンバーター アプローチを使用するには、次のようにします。

public class BasicComponentTypeConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        bool canConvert = base.CanConvertTo(context, destinationType);

        if (!canConvert &&
            (destinationType == typeof(InstanceDescriptor))
        {
            canConvert = true;
        }

        return canConvert;
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        object conversion = null;

        if (culture == null)
        {
            culture = CultureInfo.CurrentCulture;
        }

        BasicComponent component = value as BasicComponent;
        if (basicComponent != null)
        {
            if (destinationType == typeof(InstanceDescriptor))
            {
               // Note that we convert the blobs to an array as this makes for nicer persisted code output.
               // Without it, we might just get a resource blob which is not human-readable.
               conversion = new InstanceDescriptor(
                   typeof(BasicComponent).GetConstructor(new Type[] { typeof(IEnumerable<Blob>) }),
                   new object[] { basicComponent.Blobs.ToArray() },
                   true);
            }
        }

        if (conversion == null)
        {
            conversion = base.ConvertTo(context, culture, value, destinationType);
        }

        return conversion;
    }
}

型の型コンバーターも作成する必要がある場合があることに注意してくださいBlob。型コンバーターを型にアタッチするには、型コンバーターが変換するクラスの属性を宣言するだけTypeConverterです。つまり、上記の例では BasicConverter です。

于 2009-03-03T18:24:19.983 に答える