订阅WCF服务的DataContract代理classe的PropertyChanged

时间:2010-02-01 16:01:02

标签: c# .net wcf inotifypropertychanged

我喜欢使用部分类扩展作为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服务忽略了客户端的构造函数,请参阅constructor not showing up in my WCF client, serialization problem?

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

所以我很有兴趣在哪里做或者可能推断整个方法应该改变。任何想法都赞赏。

3 个答案:

答案 0 :(得分: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"));
        };
    }
}

答案 1 :(得分: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));
    }
}

答案 2 :(得分: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); }}
}