3
\$\begingroup\$

I tried to implement the dispose-finalize pattern on this WCF wrapper.

Do you have any comments about this? Something I missed?

namespace System.ServiceModel
{
    public class WCFClientWrapper<TProxy> : IDisposable where TProxy : class
    {
        private string _endpointAddress;
        public TProxy Service { get; private set; }

        public WCFClientWrapper(string endpointAddress)
        {
            _endpointAddress = endpointAddress;

            var factory = new ChannelFactory<TProxy>(new NetTcpBinding(), new EndpointAddress(endpointAddress));
            Service = factory.CreateChannel();

            (Service as IClientChannel).Faulted += WCFClientWrapper_Faulted;
        }

        private TProxy CreateChannel(string endpointAddress)
        {
            var factory = new ChannelFactory<TProxy>(new NetTcpBinding(), new EndpointAddress(endpointAddress));
            return factory.CreateChannel();
        }

        void WCFClientWrapper_Faulted(object sender, EventArgs e)
        {
            DisposeService();
            Service = CreateChannel(_endpointAddress);
        }

        public void Dispose(bool disposing)
        {
            if (disposing)
            {
                // get rid of managed resources
            }   

            DisposeService();
            GC.SuppressFinalize(this);
        }

        private void DisposeService()
        {
            IClientChannel serviceChannel = Service as IClientChannel;
            if (serviceChannel == null)
                return;

            bool success = false;
            try
            {
                (Service as IClientChannel).Faulted -= WCFClientWrapper_Faulted;

                if (serviceChannel.State != CommunicationState.Faulted)
                {
                    serviceChannel.Close();
                    success = true;
                }
            }
            finally
            {
                if (!success)
                {
                    serviceChannel.Abort();
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        ~WCFClientWrapper()
        {
            Dispose(false);
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Any final solution with full source code sample application ? IMHO, better samples for minimize learning curve are real applications with full source code and good patterns \$\endgroup\$
    – Kiquenet
    Commented Sep 25, 2014 at 8:26

2 Answers 2

2
\$\begingroup\$

Given that much of the code seems to rely on Service being an IClientChannel, and the name of the class implies as such, it may be worth simply adding IClientChannel to your type constraints and remove all the type conversion code.

Building upon that thought, I notice that IClientChannel extends IChannel, and everything you use seems to be present on IChannel. You may consider using that interface instead, and renaming your class to reflect that it is not limited to IClientChannel.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you but there is no constraint that defines an inheritance from an interface. \$\endgroup\$
    – Gil
    Commented Jan 22, 2012 at 7:55
1
\$\begingroup\$

I saw some duplication of code, which could easily be centralized and eliminated. I also renamed a few pieces as per Microsoft Framework Design Guidelines. Finally, you may also want to look at this bit of code which seems somewhat similar and caches the service proxy rather than recreating it for each call.

namespace System.ServiceModel
{
    public class WcfClientWrapper<TProxy> : IDisposable where TProxy : class
    {
        private string endpointAddress;

        private TProxy service;

        public WcfClientWrapper(string endpointAddress)
        {
            this.service = this.CreateChannel(endpointAddress);

            var serviceChannel = this.service as IClientChannel;

            if (serviceChannel == null)
            {
                return;
            }

            serviceChannel.Faulted += this.ClientChannelFaulted;
        }

        ~WcfClientWrapper()
        {
            this.Dispose(false);
        }

        public TProxy Service
        {
            get
            {
                return this.service;
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        public void Dispose(bool disposing)
        {
            if (disposing)
            {
                // get rid of managed resources
            }

            this.DisposeService();
            GC.SuppressFinalize(this);
        }

        private TProxy CreateChannel(string newEndpointAddress)
        {
            this.endpointAddress = newEndpointAddress;

            var factory = new ChannelFactory<TProxy>(new NetTcpBinding(), new EndpointAddress(newEndpointAddress));

            return factory.CreateChannel();
        }

        private void ClientChannelFaulted(object sender, EventArgs e)
        {
            this.DisposeService();
            this.service = this.CreateChannel(this.endpointAddress);
        }

        private void DisposeService()
        {
            var serviceChannel = this.service as IClientChannel;

            if (serviceChannel == null)
            {
                return;
            }

            var success = false;

            try
            {
                serviceChannel.Faulted -= this.ClientChannelFaulted;
                if (serviceChannel.State != CommunicationState.Faulted)
                {
                    serviceChannel.Close();
                    success = true;
                }
            }
            finally
            {
                if (!success)
                {
                    serviceChannel.Abort();
                }
            }
        }
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ The DisposeService() method will get called for both an explicit Dispose() and during finalization. Is this safe? \$\endgroup\$
    – ulty4life
    Commented Aug 16, 2012 at 23:06
  • \$\begingroup\$ You might want to set serviceChannel to null at the end of the DisposeService() method to be sure. \$\endgroup\$ Commented Aug 17, 2012 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.