The way WCF proxies are designed is to live until shi* happens. Let's assume that we have a CalcualtorService with one method named Divide(int a, int b). Sasha, a cool programmer-dude, trying to produce some usefull software writes:
public MyCalcualtorForm : Form { private CalculatorProxy _calc = new CalculatorProxy(); Calc_Click(...) { _calc.Divide(firstNumber, secondNumber); }}
What is the first error you can think of that could happen? Yep, DivideByZeroException.Once the proxy gets an exception, it enters into a "Faulted" state which makes the proxy unusable(=you cannot use it again). The quickest solution is to work "by the book" and create a new instance each and every time we need to call the service:
Calc_Click(...) { using (CalculatorProxy calc = new CalculatorProxy()) calc.Divide(firstNumber, secondNumber);}
But what's bad in this solution?
I had to come with a solution as no one will take TDD away from me. I present to you ProtectedProxy: this little IL-code-at-the-end-of-the-day will able you to recover from faulted state by creating a new proxy on each exception thus making your proxy... useable (couldn't think about a better word to describe it). Think about a situation where your proxy is trying to call the service but the service is down; In Semingo, we decided that we want to keep trying until the service is up. Via ProtectedProxy, you can determine how many times do you want to recover and when you should finally kill the proxy. Oh yea, ProtectedProxy uses Windsor in order to create new proxies if needed and logging messages to log4net. Good stuff.
In the example above, all Sasha had to do was to:1). Initialize the _calc field by: ProtectedProxy<ICalculatorProxy> _calc = new ProtectedProxy<ICalculatorProxy>(new CalculatorProxy());2). call _calc via: _calc.Instance.Divide(firstNumber, secondNumber);But enough said, code please:
// Written by Oren Ellenbogen (07.08.07) - trying to protect our proxies so they could recover from:// (A) The service is not up yet, but we want to try again later.// (B) The service throws (ANY) exception, we still want our proxy to function (bubble the exception, but still keep on working).// Microsoft intended to use a NEW proxy per call, but for TDD this is not ideal as we would like to inject proxies from outside as mocks// in order to simulate multiple scenarios. #region using using System;using System.Reflection;using System.ServiceModel;using Castle.Core.Resource;using Castle.Windsor;using Castle.Windsor.Configuration.Interpreters;using log4net; #endregion namespace Semingo.Services.Proxies.Helpers{ public interface IProxy : ICommunicationObject { bool Ping(); }
Hours of joy...
Almost forgot, on the next post - "How to TDD WCF code" - stay tuned...
Remember Me
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2008, Oren Ellenbogen
<= Contact me via E-mail