2014-11-21 93 views
1

我有一個MVC4應用程序調用了一些WCF服務。WCF Proxy + DI(Ninject)+ IDisposable

我閱讀了使用「using」語法處理WCF代理時可能發生的一些問題(read this...)。 我想在我的解決方案(...and now this)中正確實施WCF代理處置。

標準請求通過在應用程序以下層運行:(遺留代碼不是我的錯)

MVC控制器>「主立面」>「次要外立面」> WCF代理

我我正在使用Ninject 3.2.2.0自動將依賴關係注入到這些層中。例如:

控制器:

public class HomeController : Controller 
{ 
    private readonly SomeMainFacade _someMainFacade; 

    public HomeController(SomeMainFacade someMainFacade) 
    { 
     _someMainFacade = someMainFacade; 
    } 
    ... 
} 

「主立面」:

public class SomeMainFacade 
{ 
    private readonly MinorFacade1 _minorFacade1; 
    private readonly MinorFacade2 _minorFacade2; 

    public SomeMainFacade (
     MinorFacade1 minorFacade1, 
     MinorFacade2 minorFacade2 
     ){ 
      _minorFacade1 = minorFacade1; 
      _minorFacade2= minorFacade2; 
     } 
     ... 
} 

「小門面」

public class MinorFacade1 
{ 
    private readonly IWCFService _wcfServiceClient; 

    public MinorFacade1(IWCFService wcfServiceClient) 
    { 
     _wcfServiceClient= wcfServiceClient; 
    } 
    ... 
} 

我想處理中使用的WCF服務「小外牆」,但我想不出一個大的重構方式。也許Ninject來拯救...

任何幫助表示讚賞。

謝謝。

回答

0

這是一類我以前寫了一個很長很長的時間,在一個星系很遠很遠:

/// <summary> 
/// 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public class RemotingClient<T> : IDisposable 
{ 
    private bool _disposed; 

    private readonly ChannelFactory<T> _factory; 


    /// <summary> 
    /// 
    /// </summary> 
    public event OnCloseChannel ChannelClosed; 

    public event OnFaultedChannel ChannelFaulted; 

    /// <summary> 
    /// 
    /// </summary> 
    public delegate void OnCloseChannel(); 

    public delegate void OnFaultedChannel(); 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="factory"></param> 
    public RemotingClient(ChannelFactory<T> factory) 
     : this(factory, SynchronizationContext.Current) 
    { 
    } 

    private void OnClose(object sender, EventArgs e) 
    { 
     if (null != ChannelClosed) 
      ChannelClosed(); 
    } 

    private void OnFaulted(object sender, EventArgs e) 
    { 
     if (null != ChannelFaulted) 
      ChannelFaulted(); 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="factory"></param> 
    /// <param name="context"></param> 
    public RemotingClient(ChannelFactory<T> factory, SynchronizationContext context) 
    { 
     Context = context; 
     _factory = factory; 
     CreateNewChannel(); 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="uiCallback"></param> 
    public void PostToContext(SendOrPostCallback uiCallback) 
    { 

     Context.Post(uiCallback, null); 
    } 

    public void CreateNewChannel() 
    { 
     Channel = _factory.CreateChannel(); 

     ICommunicationObject c = Channel as ICommunicationObject; 

     if (null == c) 
      throw new ArgumentException(
       typeof(T) + " Can not be used as an ICommunicationObject"); 

     c.Closed += OnClose; 
     c.Faulted += OnFaulted; 
     c.Open(); 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    public SynchronizationContext Context 
    { get; private set; } 

    /// <summary> 
    /// 
    /// </summary> 
    public T Channel 
    { get; set; } 

    public CommunicationState ChannelState 
    { 
     get 
     { 
      ICommunicationObject c = (ICommunicationObject)Channel; 
      return c.State; 
     } 
    } 

    #region IDisposable Members 
    /// <summary> 
    /// 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    public void Dispose(bool disposing) 
    { 
     if (!this._disposed) 
     { 
      if (disposing) 
       Close(); 

      this._disposed = true; 
     } 

    } 

    public void Close() 
    { 
     ICommunicationObject c = Channel as ICommunicationObject; 

     if (c.State == CommunicationState.Faulted) 
      c.Abort(); 

     c.Close(); 

    } 

    #endregion 
} 

那麼基本上你創建一個靜態的ChannelFactory的地方(我想這是將被傳遞給您的minorfacade ),然後調用RemotingClient。像這樣:

public class MinorFacade1 
{ 
    private static ChannelFactory<IMyServiceContract> MyFactory{ get; set; } 

    public MinorFacade1(ChannelFactory<IMyServiceContract> factory) 
    { 
     MyFactory = factory; 
    } 


    public void DoSomeAwesomeWcfCall() 
    { 
     using(RemotingClient<IMyServiceContract> proxy = new RemotingClient<IMyServiceContract>(MyFactory) 
      proxy.Channel.ThisIsAnAwesomeWcfCall(); 
    } 

}