Хотя вы можете использовать объекты данных, возвращаемые вашими службами в вашей модели, есть несколько причин, чтобы этого избежать:
- В конечном итоге вы можете ввести требования к привязке данных ( INotifyPropertyChanged , INotifyCollectionChanged , IDataErrorInfo и т. Д.) В объекты данных службы.
- Становится все труднее развивать службу и приложение WPF независимо друг от друга.особенно в случае, когда служба может использоваться несколькими приложениями.
Вместо этого вам следует рассмотреть возможность использования Repository Pattern в вашей модели для инкапсуляции вашей коммуникации службы в качестве одного или несколькихрепозитории веб-сервисов.Репозитории веб-сервисов позволяют централизовать логику доступа к сервису и обеспечивают точку замены для модульных тестов, а также дают возможность кэшировать результаты предыдущих операций сервиса.
Репозитории действуют как мосты между данными иоперации, которые находятся в разных доменах.Хранилище отправляет соответствующие запросы к источнику данных, а затем сопоставляет результирующие наборы с бизнес-объектами, как правило, используя шаблон Data Mapper для преобразования между представлениями.
Ваши модели представлений будутиспользуйте хранилище службы для извлечения или сохранения информации, причем хранилище обрабатывает вызов службы и сопоставляет представление службы с данными для классов, специфичных для модели, к которым вы в конечном итоге привязываете данные.
Вы можетеперейдите на шаг вперед и определите универсальные интерфейсы для репозитория сервисов, которые могут позволить вам реализовать репозитории, специфичные для сервисов, на основе операций 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);
}