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); }}
}

现在我想确保无论何时位置或大小发生变化,都会调用 Bounds chage 事件。通过代码很容易做到:

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

问题是放置此代码的好地方在哪里。

如果对象不是由服务调用创建的,我会将其放入构造函数中。但是 WCF 服务忽略客户端的构造函数,看到构造函数没有出现在我的 WCF 客户端中,序列化问题?.

现在,在服务响应之后,我的程序立即搜索数据契约层次结构,获取所需的对象并添加事件处理程序。但我不认为这是一件正确的事情。

所以我很感兴趣在哪里做更好,或者,也许,推理应该改变整个方法。任何想法表示赞赏。

4

3 回答 3

4

您可以使用 [OnDeserlialized] 属性插入在反序列化后调用的方法。

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 回答