2016-03-01 72 views
0

在開發允許編輯文章和載體(托盤,貨架)數據(以CRUD方式)的WPF應用程序中,我正在尋找如何管理WPF應用程序的生命週期WCF客戶端連接到包含實際數據的服務。如何在WPF應用程序中管理WCF客戶端的生命週期

我更喜歡使用使用Caliburn Micro和StructureMap或Castle Windsor的MVVM方法。

我的主要問題不是創建WCF客戶端渠道或工廠,而是更重要的是使用後的清理。我打算在服務器端使用per-request生命週期,因此我需要根據每個請求創建和處理我的客戶端。這樣我心裏有以下幾點:

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在發送操作上創建一個新的嵌套容器,並在發送操作完成後將其放置,但它似乎很麻煩。

我是否弄錯了所有的錯誤,還是僅僅需要付出很大的努力才能從WPF應用程序執行WCF調用?

作爲一個旁註,我將擁有比這些少數幾個CRUD服務更多的服務,所以在我的CRUD服務中解決這個問題的可能實用的解決方案不是一種選擇。

+0

講述的是WCF會話壽命這個問題? – Jasper

+0

不,我想通過會話PerRequest保持WCF層儘可能薄。 – mycroes

回答

0

我已經處理了相同的問題(在WPF應用程序中使用WCF服務),並希望使用ServiceInterface而不是ServiceClient(這是IDisposable,可用於使用塊)。

一個解決關閉連接的是接口轉換爲客戶型和調用.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 { ... } 
} 
+0

我認爲你可能意味着轉換爲'IChannel'或'ICommunicationObject'並關閉它,我沒有在'IArticleCrud'上的'Close()',並且我甚至沒有客戶端中的'ArticleCrud'(記住,它只是一個WCF代理)。另外,'Close()'對我來說不夠安全(需要嘗試/捕獲並在出錯時中止)。 – mycroes

+0

請編輯您的問題,並指定您只使用WCF代理或其他人可能認爲您正在實施該服務與「右鍵點擊添加新的ServiceReference」,然後生成接口和客戶端(IArticleCrud和ArticleCrudClient在你的情況下)。 –

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<>)) 
+0

我打算'IArticleCrud'作爲WCF服務的ServiceContract,但更重要的是您的WcfServiceCommandHandlerProxy實現控制着服務的創建,我希望從IoC獲得它來從一個地方控制它,這將我帶回原始問題。 – mycroes

+0

@mycroes這個'WcfServiceCommandHandlerProxy'只做一件事 - 創建和配置WCF客戶端。如果你需要更多的責任裝飾它,並與另一個類包裝這一個。執行後不應該改變WcfServiceCommandHandlerProxyclass。 IoC現在對生活無所作爲。 IoC只知道'WcfServiceCommandHandlerProxyclass'實現'IRequestHandler'。 – Szer

+0

'ActualWcfServiceClient()'在其他地方強加約束,例如我需要爲地址/綁定執行XML配置,或者將它們放在這裏。此外,我不使用生成的WCF客戶端,但我使用服務接口來生成代理。 – mycroes

相關問題