DCSIMG
November 2007 - Posts - Nati Dobkin

November 2007 - Posts

When you first time run your WCF service (http://localhost/myCoolService.svc) you get a nice tutorial, made by Microsoft, that explain you how you should use the service. This is not hard to notice that you should close every connection you made to a service. Like this:

MyServiceClient client = new MyServiceClient();
client.Close();

I am using a lot of services in my apps and I don’t want to kip in mind that all the time I am using a service instance I have to remember to close the connection. So I wrote a simple code that handles the closing for me.

public class ServicesFactory : IDisposable
{
    List<object> services;

    public ServicesFactory()
    {
        services = new List<object>();
    }

    public T CreateService<T>() where T : ICommunicationObject
    {
        T service = Activator.CreateInstance<T>();
        services.Add(service);
        return service;
    }

    #region IDisposable Members

    public void Dispose()
    {
        foreach (object obj in services)
        {
            ICommunicationObject currService = (ICommunicationObject)obj;
            if (currService.State != CommunicationState.Closed)
                currService.Close();
        }

    }

    #endregion
}

Now every time I will create a service instance I will do it this way.

using (ServicesFactory factory = new ServicesFactory())
{
    WCFServiceEx.Client.Calculate.CalculateClient client = 
                            factory.CreateService<WCFServiceEx.Client.Calculate.CalculateClient>();

    // do service logic.
}

That will make shore that the connection of all the instances that I made in the scope will be closed as soon as the code in the scope will finished.

Posted by Nati Dobkin | with no comments

 

WCF provides nice capability of extending the behavior of operations by implementing IOperationBehavior interface. I want to concentrate on ApplyDispatchBehavior method of that interface, which purpose is to do extention to server side calls. I will show how I use this extensability to provide a nice and easy cache mechanisam.

I will make a class which derives from Attribute class and implements an IOperationBehavior interface. Now I want to interfire in the invoke process of the method so I need to make another class that implements IOperationInvoker interface and would hold the cache logic. And then set it to dispatch.Invoker property of the ApplyDispatchBehavior method. Let see some code:

class CacheMeAttribute: Attribute, IOperationBehavior
{
    #region IOperationBehavior Members
    public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
    {
        dispatch.Invoker = new CommonInvoker(dispatch.Invoker);
    }
    //other interface methods.
    
    #endregion
} 
class CommonInvoker : IOperationInvoker
{
    public Cache AppCache
    {
        get
        {
            return HttpRuntime.Cache; 
        }
    }

    IOperationInvoker BaseInvoker;
        
    public CommonInvoker(IOperationInvoker baseInvoker)
    {
        this.BaseInvoker = baseInvoker;
    }
        
    
    #region IOperationInvoker Members

    public object[] AllocateInputs()
    {
        object[] ret = this.BaseInvoker.AllocateInputs();
        return ret;
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        string key = GetCacheKey(inputs);
        object result = AppCache[key];
        if (result == null)
        {
            result = this.BaseInvoker.Invoke(instance, inputs, out outputs);
            AppCache[key] = result;
        }
        outputs = new object[0];
        return result;
     }

     // other interface methods.

      #endregion

    private string GetCacheKey(object[] inputs)
    {
        string key = string.Empty;
        for (int i = 0; i < inputs.Length; i++)
             key += inputs[0].ToString();
        return key;
    }
}

The cache algorithm is shown in the Invoke method and cache the return value of the calling method by the parameters given to the method input. I use HttpRuntime.Cache for the caching and it work well for both win and web application as I explained in my last post.

Now all you have to do in order to cache data is add CacheMe attribute over a method like this:

[ServiceContract(Namespace = "Dobkin.Services")]
interface IMyService
{
    [OperationContract]
    string Mult(int x, int y);
}

class MyService : IMyService
{
    [CacheMe]
    public long Mult(int x, int y)
    {
        return x * y;
    }
} 

And that's it. Now every time that Mult method will be called then the CommonInvoker will check if there is entry in the cache with a 'xy' key. If there is, the value will be returned to the caller without executing the method.

See full example of the code here.

Posted by Nati Dobkin | 5 comment(s)
תגים:,

 

Asp.Net provides us very powerful cache mechanism that can be found under System.Web.Caching. You can access the cache using the folioing syntax:

HttpContext.Current.Cache["key"] = value;

HttpContext.Current.Cache.Add(params...);

Lately I was looking for similar mechanism to use with WCF. The flax ability of WCF services provide them to live in supported as well not supported web environment. In that case HttpContext.Current would not be available. From curiosity I went and check how the HttpContext.Current.Cache property is implemented and I was surprised to see the all it does is: return HttpRuntime.Cache. After googling I was more suprized to find out that inspite it very weby name (you know Http…) it is not have to live in web supported envirment. The only check that made by this getter is 'if ASPNet is installed on the machine' and as far as I know it come with the installation of FrameWork.

The only explanation that I can see for this one is that the Cache class is places in not appropriate namespace.

So there is no matter how you will host you WCF service, within IIS (web app) or console app, you can use the cache mechanism by accessing HttpRuntime.Cache.

Some of you may say: "wait a minute, I am writhing a console application, why the hell do I need a reference to System.Web?" and I will agree that usually you don’t. But till Microsoft will come up with some appropriate solution for caching in client apps, I think this deviation from the common sense worth it.

 

There are some references on the issue:

http://www.hanselman.com/blog/UsingTheASPNETCacheOutsideOfASPNET.aspx

http://weblogs.asp.net/pjohnson/archive/2006/02/06/437559.aspx

Posted by Nati Dobkin | 1 comment(s)
תגים:,

 

Recently I been refactoring some legasy code and writing a new one. I am using Rhino mocks to run my units and for that I have to write my code in a testable way. This approach makes my code looks not exactly the way I designed and want it to be. Eli Lopian wrote an article about this issue – "Stop Designing for Testability" and has some points to think of.

In my opinion, if we have to write very simple code to encapsulate some internal logic for our base class and make sure that there is no way some smart ass will override it, but still give an opportunity to reuse this code in the deriving class, like this:

public abstract class MyBase
{
    protected void DoSomeVeryImportentLogicThatCanotBeOverriden()
    {
        DoTheSameVeryImportentLogic();
    }

    internal virtual void DoTheSameVeryImportentLogic()
    {
        // logic goes there.
    }
}

Only to make the code testeble – we are missing something – this is not the way code should look like.

There is also the impact on performance of making all our methods as virtual, to be able to override them when we make out mock classes, I agree with Roy Osherove one this on and we are not dealing here with real-time applications so the impact of the vtable that created when we are performing polymorphism (you can read about it from Shimon's post) is not so painful. And as Roy explained in his post if this is your pain in the ass you can deal with it.

I don’t really like the idea of losing the concept of OOP and clear and simple code writing over testable code.

What do you think?

Posted by Nati Dobkin | 3 comment(s)
תגים: