Wpf MVVM和服务对象
我们目前正在设计一个使用WPF的系统,该系统将使用web服务与其他系统进行通信 我们正在尝试尽可能少的层和映射(通过坚持最简单的方法来降低成本) 我们将使用MVVM模式 所以我们必须有一个视图模型Wpf MVVM和服务对象,wpf,web-services,architecture,mvvm,Wpf,Web Services,Architecture,Mvvm,我们目前正在设计一个使用WPF的系统,该系统将使用web服务与其他系统进行通信 我们正在尝试尽可能少的层和映射(通过坚持最简单的方法来降低成本) 我们将使用MVVM模式 所以我们必须有一个视图模型 问题是,我们可以使用从服务返回的对象作为模型对象,还是应该将这些对象映射到客户端中定义的模型对象?您不必创建自己的模型层,但是:如果服务发生更改,您必须在引用模型的所有层中反映这些更改。如果现在创建自己的模型层,则会更安全,但工作量会更大。正如经常发生的那样:更多的工作最终会为你节省更多的工作。如果您
问题是,我们可以使用从服务返回的对象作为模型对象,还是应该将这些对象映射到客户端中定义的模型对象?您不必创建自己的模型层,但是:如果服务发生更改,您必须在引用模型的所有层中反映这些更改。如果现在创建自己的模型层,则会更安全,但工作量会更大。正如经常发生的那样:更多的工作最终会为你节省更多的工作。如果您拥有该服务,并且确信永远不会更改它(哈哈),则不需要模型层
当然,这取决于服务检索到的对象是否完全符合您的需要。如果您使用大型对象的1、2个属性,这可能不是一个很好的选择…是的,您可以使用WCF服务对象作为您的模型层(我们是),尽管如@fantasticfix所说,如果您的WCF服务器对象发生更改,您必须查找引用以修复它们
此外,如果要将整个模型公开给视图并绑定到模型的属性,则需要确保WCF服务器对象实现
INotifyPropertyChanged
,而您可以在模型中使用从服务返回的数据对象,有几个原因可以避免这种情况:
您应该考虑使用模型内的服务来封装您的服务通勤作为一个或多个Web服务库。Web服务存储库允许您集中服务的访问逻辑,并为单元测试提供替换点,同时也为您提供了缓存以前服务操作结果的机会
存储库充当不同域中的数据和操作之间的桥梁。存储库向数据源发出适当的查询,然后将结果集映射到业务实体,通常使用模式在表示之间进行转换 您的视图模型将使用服务存储库来检索或持久化信息,存储库将处理对服务的调用,并将数据的服务表示映射到您最终将绑定到的特定于模型的类 您可以更进一步,为服务存储库定义通用接口,使您能够围绕应用程序可能执行的基于CRUD的操作实现特定于服务的存储库 通用服务存储库接口示例:/// <summary>
/// Describes a service repository that separates the logic that retrieves, persists and maps data to the
/// domain model from the business logic that acts on the domain model.
/// </summary>
/// <typeparam name="TChannel">The type of channel produced by the channel factory used by the repository.</typeparam>
/// <typeparam name="TMessage">The type of data contract to map to the domain entity of type <typeparamref name="T"/>.</typeparam>
/// <typeparam name="T">The type of domain entity mediated by the repository.</typeparam>
/// <typeparam name="TKey">The type of the key that uniquely identifies domain entities within the repository.</typeparam>
public interface IServiceRepository<TChannel, TMessage, T, TKey> : IRepository<T, TKey>
where T : class
{
/// <summary>
/// Occurs when the repository transitions from one state to another.
/// </summary>
event EventHandler<StateChangedEventArgs> StateChanged;
/// <summary>
/// Gets the configuration name used for the service endpoint.
/// </summary>
/// <value>
/// The name of the endpoint in the application configuration file that is used
/// to create a channel to the service endpoint.
/// </value>
string EndpointConfigurationName
{
get;
}
/// <summary>
/// Gets the current state of the service repository.
/// </summary>
/// <value>
/// The current <see cref="CommunicationState"/> of the service repository.
/// </value>
CommunicationState State
{
get;
}
}
/// <summary>
/// Describes a repository that separates the logic that retrieves, persists and maps data to the domain model
/// from the business logic that acts on the domain model.
/// </summary>
/// <typeparam name="T">The type of domain entity mediated by the repository.</typeparam>
/// <typeparam name="TKey">The type of the key that uniquely identifies domain entities within the repository.</typeparam>
public interface IRepository<T, TKey>
where T : class
{
/// <summary>
/// Occurs when a repository action has been completed.
/// </summary>
event EventHandler<RepositoryActionCompletedEventArgs<T>> Completed;
/// <summary>
/// Occurs when a repository action fails to execute.
/// </summary>
event EventHandler<RepositoryActionFailedEventArgs<T>> Failed;
/// <summary>
/// Gets a value indicating if the repository has been disposed of.
/// </summary>
/// <value>
/// <see langword="true" /> if the repository has been disposed of; otherwise, <see langword="false" />.
/// </value>
bool IsDisposed
{
get;
}
/// <summary>
/// Adds a new <paramref name="entity"/> to the data source layer.
/// </summary>
/// <param name="entity">The entity of type <typeparamref name="T"/> to insert into the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is insert into the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Add(T entity, Action<T, Exception> callback = null);
/// <summary>
/// Retrieves all entities of type <typeparamref name="T"/> from the data source layer.
/// </summary>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after all entities of type <typeparamref name="T"/> are retrieved from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
IRepository<T, TKey> Get(Action<IEnumerable<T>, Exception> callback = null);
/// <summary>
/// Retrieves an entity of type <typeparamref name="T"/> from the data source layer that
/// matches the specified <paramref name="key"/>.
/// </summary>
/// <param name="key">The unique identifier of the entity of type <typeparamref name="T"/> to retrieve from the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after an entity of type <typeparamref name="T"/> that matches the specified <paramref name="key"/> is retrieved from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
IRepository<T, TKey> Get(TKey key, Action<T, Exception> callback = null);
/// <summary>
/// Removes an existing <paramref name="entity"/> from the data source layer.
/// </summary>
/// <param name="entity">An entity of type <typeparamref name="T"/> to delete from the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is removed from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Remove(T entity, Action<T, Exception> callback = null);
/// <summary>
/// Updates an existing <paramref name="entity"/> within the data source layer.
/// </summary>
/// <param name="entity">The entity of type <typeparamref name="T"/> to update within the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is updated within the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Update(T entity, Action<T, Exception> callback = null);
}
//
///描述一个服务存储库,该存储库分离用于检索、持久化数据并将数据映射到
///来自作用于域模型的业务逻辑的域模型。
///
///存储库使用的通道工厂生成的通道类型。
///要映射到类型为的域实体的数据协定类型。
///存储库介导的域实体的类型。
///唯一标识存储库中的域实体的密钥类型。
公共接口IServiceRepository:IRepository
T:在哪里上课
{
///
///当存储库从一种状态转换到另一种状态时发生。
///
事件处理程序状态已更改;
///
///获取用于服务端点的配置名称。
///
///
///所使用的应用程序配置文件中端点的名称
///创建到服务端点的通道。
///
字符串EndpointConfigurationName
{
得到;
}
///
///获取服务存储库的当前状态。
///
///
///服务存储库的当前名称。
///
通讯状态
{
得到;
}
}
通用存储库接口示例:
/// <summary>
/// Describes a service repository that separates the logic that retrieves, persists and maps data to the
/// domain model from the business logic that acts on the domain model.
/// </summary>
/// <typeparam name="TChannel">The type of channel produced by the channel factory used by the repository.</typeparam>
/// <typeparam name="TMessage">The type of data contract to map to the domain entity of type <typeparamref name="T"/>.</typeparam>
/// <typeparam name="T">The type of domain entity mediated by the repository.</typeparam>
/// <typeparam name="TKey">The type of the key that uniquely identifies domain entities within the repository.</typeparam>
public interface IServiceRepository<TChannel, TMessage, T, TKey> : IRepository<T, TKey>
where T : class
{
/// <summary>
/// Occurs when the repository transitions from one state to another.
/// </summary>
event EventHandler<StateChangedEventArgs> StateChanged;
/// <summary>
/// Gets the configuration name used for the service endpoint.
/// </summary>
/// <value>
/// The name of the endpoint in the application configuration file that is used
/// to create a channel to the service endpoint.
/// </value>
string EndpointConfigurationName
{
get;
}
/// <summary>
/// Gets the current state of the service repository.
/// </summary>
/// <value>
/// The current <see cref="CommunicationState"/> of the service repository.
/// </value>
CommunicationState State
{
get;
}
}
/// <summary>
/// Describes a repository that separates the logic that retrieves, persists and maps data to the domain model
/// from the business logic that acts on the domain model.
/// </summary>
/// <typeparam name="T">The type of domain entity mediated by the repository.</typeparam>
/// <typeparam name="TKey">The type of the key that uniquely identifies domain entities within the repository.</typeparam>
public interface IRepository<T, TKey>
where T : class
{
/// <summary>
/// Occurs when a repository action has been completed.
/// </summary>
event EventHandler<RepositoryActionCompletedEventArgs<T>> Completed;
/// <summary>
/// Occurs when a repository action fails to execute.
/// </summary>
event EventHandler<RepositoryActionFailedEventArgs<T>> Failed;
/// <summary>
/// Gets a value indicating if the repository has been disposed of.
/// </summary>
/// <value>
/// <see langword="true" /> if the repository has been disposed of; otherwise, <see langword="false" />.
/// </value>
bool IsDisposed
{
get;
}
/// <summary>
/// Adds a new <paramref name="entity"/> to the data source layer.
/// </summary>
/// <param name="entity">The entity of type <typeparamref name="T"/> to insert into the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is insert into the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Add(T entity, Action<T, Exception> callback = null);
/// <summary>
/// Retrieves all entities of type <typeparamref name="T"/> from the data source layer.
/// </summary>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after all entities of type <typeparamref name="T"/> are retrieved from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
IRepository<T, TKey> Get(Action<IEnumerable<T>, Exception> callback = null);
/// <summary>
/// Retrieves an entity of type <typeparamref name="T"/> from the data source layer that
/// matches the specified <paramref name="key"/>.
/// </summary>
/// <param name="key">The unique identifier of the entity of type <typeparamref name="T"/> to retrieve from the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after an entity of type <typeparamref name="T"/> that matches the specified <paramref name="key"/> is retrieved from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
IRepository<T, TKey> Get(TKey key, Action<T, Exception> callback = null);
/// <summary>
/// Removes an existing <paramref name="entity"/> from the data source layer.
/// </summary>
/// <param name="entity">An entity of type <typeparamref name="T"/> to delete from the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is removed from the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Remove(T entity, Action<T, Exception> callback = null);
/// <summary>
/// Updates an existing <paramref name="entity"/> within the data source layer.
/// </summary>
/// <param name="entity">The entity of type <typeparamref name="T"/> to update within the data source layer.</param>
/// <param name="callback">
/// The optional <see langword="delegate"/> method that will be executed after the <paramref name="entity"/> is updated within the data source layer.
/// </param>
/// <returns>
/// The <see cref="IRepository{T, Tkey}"/> object that this method was called on.
/// </returns>
/// <exception cref="ArgumentNullException">The <paramref name="entity"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
IRepository<T, TKey> Update(T entity, Action<T, Exception> callback = null);
}
//
///描述一个存储库,该存储库分离用于检索、持久化数据并将数据映射到域模型的逻辑
///从作用于域模型的业务逻辑。
///
///存储库介导的域实体的类型。
///唯一标识存储库中的域实体的密钥类型。
公共接口假定
T:在哪里上课
{
///
///在存储库操作完成时发生。
///
事件处理程序已完成;
///
///当存储库操作无法执行时发生。
///
事件处理程序失败;
///
///获取一个值,该值指示存储库是否已被释放。
///
///
///如果存储库已被处置,则为。
///
布勒被揭穿了
{
得到;
}
///
///向数据源层添加新的。
///
///要插入到数据源层中的类型的实体。
///
///将插入数据源层后将执行的可选方法。
///
///
///调用此方法的对象。
///
///是一个引用(在Visual Basic中没有)。
i正向添加(T实体,动作回调=null);
///
///从数据源层检索类型为的所有实体。
///
///
///从数据源层检索所有类型的实体后将执行的可选方法。
///
///
///调用此方法的对象。
///
IRepository Get(操作回调=null);
///
///从要删除的数据源层检索类型为的实体
///匹配指定的。
///
///实体o的唯一标识符