4

部分的なクラスを使用して、WCFサービスのデータコントラクトであるクライアント側のクラスを拡張するというアイデアが好きです。しかし、私はパーティーをかなり台無しにする問題に遭遇しました。

サーバー側でクラスがあると想像してください。

[DataContract]
public class SolidObject
{
    [DataMember]
    public Point Position { get; set; }
    [DataMember]
    public Size Size { get; set; }
}

クライアント側では、プロキシクラスが生成され、ビジネスロジック層で使用されます。ビジネスロジックのニーズに応じて、次のように拡張します。

public partial class SolidObject
{
    public Rect Bounds { get { return new Rect(Position.X - Size.Width / 2, Position.Y - Size.Height / 2, Size.Width, Size.Height); }}
}

ここで、PositionまたはSizeのいずれかが変更されたときに、Boundschageイベントが呼び出されるようにします。コードで簡単に実行できます。

PropertyChanged += (sender, e) =>
    {
        if ((e.PropertyName == "Position") || (e.PropertyName == "Size")) PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Bounds"));
    };

問題は、このコードを配置するのに適した場所がどこにあるかです。

オブジェクトがサービス呼び出しによって作成されていない場合は、コンストラクターに入れます。しかし、WCFサービスはクライアント側のコンストラクターを無視します。コンストラクターがWCFクライアントに表示されない、シリアル化の問題を参照してください。

これで、サービス応答の直後に、プログラムはデータコントラクト階層を検索し、目的のオブジェクトを取得して、イベントハンドラーを追加します。しかし、それは正しいことではないと思います。

ですから、どこでやったほうがいいのか、あるいはアプローチ全体を変えるべきだと考えているのか、興味があります。どんなアイデアでもありがたいです。

4

3 に答える 3

4

[OnDeserlialized]属性を使用して、deserizlizationの後に呼び出されるメソッドを挿入できます。

public partial class SolidObject
{
    public Rect Bounds
    {
        get
        {
            return new Rect(Position.X - Size.Width / 2, Position.Y - Size.Height / 2, Size.Width, Size.Height);
        }
    }

    [OnDeserialized]
    public void Initialize(StreamingContext streamingContext)
    {
        PropertyChanged += (sender, e) =>
        {
            if ((e.PropertyName == "Position") || (e.PropertyName == "Size"))
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Bounds"));
        };
    }
}
于 2010-02-19T16:05:20.833 に答える
2

部分的なクラスではなく、ビューモデルを使用することをお勧めします。

public class SolidObjectViewModel : INotifyPropertyChanged
{
    private SolidObject _solidObject;

    public SolidObjectViewModel(SolidObject solidObject)
    {
        _solidObject = solidObject;
        _solidObject.PropertyChanged += (sender, e) =>
        {
            bool positionChanged = e.PropertyName == "Position";
            bool sizeChanged = e.PropertyName == "Size";
            if (positionChanged)
                FirePropertyChanged("Position");
            if (sizeChanged)
                FirePropertyChanged("Size");
            if (positionChanged || sizeChanged)
                FirePropertyChanged("Bounds");
        };
    }

    public Point Position
    {
        get { return _solidObject.Position; }
        set { _solidObject.Position = value; }
    }

    public Size Size
    {
        get { return _solidObject.Size; }
        set { _solidObject.Size = value; }
    }

    public Rect Bounds
    {
        get
        {
            return new Rect(Position.X - Size.Width / 2, Position.Y - Size.Height / 2, Size.Width, Size.Height);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
于 2010-02-05T18:58:03.283 に答える
0

実装するビジネスロジックがある場合は、生成されたクラスを使用しないでください。SolidObjectをクライアント側で実装することにより、モデルをクリーンに保ちます。プロキシを生成するときは、このdllからクラスを再利用するオプションを使用できます。

エンティティが独自のイベントにアタッチすることは意味がありません。実装は次のようになります。

[DataContract]
public class SolidObject
{
   [DataMember]
   public Point Position
    {
        get { return _position; }
        set 
          { 
           position = value; 
           FirePropertyChanged("Position");
           FirePropertyChanged("Bounds");
           }
    }

    public Size Size
    {  
     //similar to position
    }

    public Rect Bounds { get { return new Rect(Position.X - Size.Width / 2, Position.Y - Size.Height / 2, Size.Width, Size.Height); }}
}
于 2010-02-06T20:02:50.847 に答える