我喜欢使用部分类扩展作为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?。
现在,在服务响应之后,我的程序搜索数据合同层次结构,获取所需对象并添加事件处理程序。但我认为这不是一件正确的事。
所以我很有兴趣在哪里做或者可能推断整个方法应该改变。任何想法都赞赏。
答案 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); }}
}