开发允许编辑文章和载体(托盘,货架)数据的WPF应用程序(以CRUD方式)我正在研究如何管理连接到包含实际数据的服务的WCF客户端的生命周期
我更喜欢使用Caliburn Micro和StructureMap或Castle Windsor的MVVM方法。
我的主要问题不是创建WCF客户端渠道或工厂,更重要的是使用后的清理。我打算在服务器端使用每个请求的生命周期,因此我需要根据请求创建和部署我的客户端。因此,我有以下几点:
public class Article
{
public int Id { get; set; }
public string ArticleId { get; set; }
}
[ServiceContract]
public interface IArticleCrud
{
[OperationContract]
Article CreateArticle(string articleId);
[OperationContract]
void Delete(int articleId);
}
public class ArticlesViewModel
{
private readonly Func<IArticleCrud> articleCrudFactory;
public ArticlesViewModel(Func<IArticleCrud> articleCrudFactory)
{
this.articleCrudFactory = articleCrudFactory;
}
public void Delete(int articleId)
{
// Doesn't work since IArticleCrud is not IDisposable
using (var crud = articleCrudFactory())
{
crud.Delete(articleId);
}
}
}
如评论中所述,这不起作用,因为IArticleCrud不是IDisposable。 IArticleCrud用于在客户端创建ChannelFactory,以便为实现相同接口的服务生成代理。我很高兴换掉以下代码:
public class DeleteArticleCommand : IRequest
{
public int Id { get; set; }
}
public class ArticlesViewModel
{
private readonly IMediator mediator;
public ArticlesViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public void Delete(int articleId)
{
mediator.Send(new DeleteArticleCommand {Id = articleId});
}
}
public class DeleteArticleCommandHandler : RequestHandler<DeleteArticleCommand>
{
private readonly IArticleCrud articleCrud;
public DeleteArticleCommandHandler(IArticleCrud articleCrud)
{
this.articleCrud = articleCrud;
}
protected override void HandleCore(DeleteArticleCommand message)
{
articleCrud.Delete(message.Id);
}
}
然而,这并没有解决我的问题,因为我仍然没有处理WCF客户端的处理。然而,我可以让IMediator在Send动作上创建一个新的嵌套容器,并在Send动作完成后将其释放,但这似乎很麻烦。
我是不是错了,或者仅仅需要花费很多精力才能从WPF应用程序执行WCF调用?
作为旁注,我将提供的服务不仅仅是这几个CRUD服务,因此在我的CRUD服务中解决此问题的可能实用解决方案不是一种选择。
答案 0 :(得分:0)
我已经处理了同样的问题(WPF应用程序中使用的WCF服务),并希望使用ServiceInterface而不是ServiceClient(它是IDisposable,可以在using-block中使用)。
关闭连接的解决方案之一是将接口转换为Client类型并调用.Close() - 方法:
public class Article
{
public int Id { get; set; }
public string ArticleId { get; set; }
}
public interface IArticleCrud
{
Article CreateArticle(string articleId);
void Delete(int articleId);
}
public class ArticlesViewModel
{
private readonly Func<IArticleCrud> articleCrudFactory;
public ArticlesViewModel(Func<IArticleCrud> articleCrudFactory)
{
this.articleCrudFactory = articleCrudFactory;
}
public void Delete(int articleId)
{
//Using-Block doesn't work since IArticleCrud is not IDisposable
var crud = articleCrudFactory();
crud.Delete(articleId);
if (crud is ArticleCrud)
(crud as ArticleCrud).Close();
}
}
您还可以在articleCrudFactory中创建一个静态方法来关闭您的IArticleCrud:
public static void CloseInterface(IArticleCrud crud)
{
if (crud is ArticleCrud)
(crud as ArticleCrud).Close();
else { ... }
}
答案 1 :(得分:0)
我已经使用WCF和MVVM完成了它并且非常简单(如果我的问题正确):
public interface IRequest
{
}
public interface IRequestHandler<in TCommand> where TCommand : IRequest
{
void HandleCore(TCommand command);
}
public class DeleteArticleCommand : IRequest
{
public int Id { get; set; }
}
public class ArticlesViewModel
{
private readonly IRequestHandler<DeleteArticleCommand> _handler;
public ArticlesViewModel(IRequestHandler<DeleteArticleCommand> handler)
{
_handler = handler;
}
public void Delete(int articleId)
{
_handler.HandleCore(new DeleteArticleCommand { Id = articleId });
}
}
//On client side
public sealed class WcfServiceCommandHandlerProxy<TCommand>
: IRequestHandler<TCommand> where TCommand : IRequest
{
public void HandleCore(TCommand command)
{
using (var service = new ActuaclWcfServiceClient())
{
service.Send(command); //Or however you are working with you WCF client
}
}
}
//Somewhere on server side
public class DeleteArticleCommandHandler : IRequestHandler<DeleteArticleCommand>
{
private readonly IArticleCrud _articleCrud;
public DeleteArticleCommandHandler(IArticleCrud articleCrud)
{
_articleCrud = articleCrud;
}
public void HandleCore(DeleteArticleCommand message)
{
articleCrud.Delete(message.Id);
}
}
只需注册要使用IRequestHandler
类型实施的WcfServiceCommandHandlerProxy
界面即可:
//May vary :)
Register(typeof (ICommandHandler<>), typeof (WcfServiceCommandHandlerProxy<>))