2014-11-21 62 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(); 
    } 

}