public class WatchedServiceAgentProxy : IWatchedServiceAgent, IDisposable
{
   internal readonly Uri agentAddress;
   private IWatchedServiceAgent agentProxy = null;
   private int failures = 0;
   private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
   private const int MAX_FAILURES = 3;
   private readonly ResourceContractInfo resourceContractInfo;

public WatchedServiceAgentProxy(
                 ResourceContractInfo resourceContractInfo,
                 int instanceIdentifier)
{
    this.resourceContractInfo = resourceContractInfo;
    agentAddress = AgentAddressProvider.GetAddress(resourceContractInfo, instanceIdentifier); 
} 

public Uri Address 
{
    get { return agentAddress; }
}

public void Dispose()
{
    if(this.agentProxy != null)
       ((ICommunicationObject)agentProxy).Abort();
}

void EnsureAgentProxy()
{
   if (agentProxy == null)
     agentProxy =
     ChannelFactory<IWatchedServiceAgent>.CreateChannel(
                      new NetNamedPipeBinding(), 
                      new EndpointAddress(agentAddress));
                      }
}

void RenewFaultedAgentProxy()
{
         if(agentProxy != null)
            ((ICommunicationObject)agentProxy).Abort();

         agentProxy = null;
         EnsureAgentProxy();
}

public LivelinessResult IsAlive()
{
    try
    {
        EnsureAgentProxy();
        var isAlive = agentProxy.IsAlive();
        return isAlive;
    }
    catch(CommunicationException ex)
    {
        throw new ServiceCommunicationException("wywoanie metody IsAlive nie powiodo si", ex);
    }
}

public string GetName()
{
    EnsureAgentProxy();
    return agentProxy.GetName();
}

public void Shutdown()
{
    EnsureAgentProxy();
    agentProxy.Shutdown();
}

public void AcceptResourcesStatusBroadcast(ServiceStatus[] resourcesStatus)
{
    try
    {
        EnsureAgentProxy();
        agentProxy.AcceptResourcesStatusBroadcast(resourcesStatus); 
        Interlocked.Exchange(ref failures, 0);
    }
    catch(CommunicationException ex)
    {
       if (resourceContractInfo.IsOptional)
       {
          log.Info(string.Format("zasb opcjonalny '{0}' nie moe by pobrany, ignorujemy", resourceContractInfo.ContractName));
           return;
       }
       if (failures > MAX_FAILURES)
       {
          log.WarnFormat("Nie uzyskano dostpu do agenta stranika na potoku '{0}' {1} razy pod rzd. Wznawianie agenta proxy, exception={2}", agentAddress, MAX_FAILURES + 1,ex);
          RenewFaultedAgentProxy();
          Interlocked.Exchange(ref failures, 0);
       }
       Interlocked.Increment(ref failures);
    }
   }
}
