Tuesday, January 13, 2009

Really weird C# code

My ServiceLocator (which has been further updated since my last post on it, so on the off chance that anybody wants the latest version, leave me a comment) can only register functions with no parameters - Func<T>. What happens if one wants to register a function with one or more parameters?

As an example, let's say that I have many possible connection strings, and in some cases when I want an instance of DataContext I have to initialize it with one of those. Since my ServiceLocator doesn't accept functions with parameters, I cannot write

    var dc = ServiceLocator.GetInstanceOf<DataContext>(connectionString); 

Here's a way of transforming a function with parameters to one without: create a function that returns the original function. That is, given

    Func<T1, T> f; 

I need another function that will return f:

    Func<Func<T1, T>> g = () => (a) => f(a);   

So, in order to register my DataContext I am now going to use the following syntax:

    Bind<Func<string, DataContext>>.To(() => (connectionString => new DBDataContext(connectionString))); 

and to retrieve the instance and initialize it correctly, I must use:

    var dc = ServiceLocator.GetInstanceOf<Func<string, DataContext>>()(connectionString); 

Not extremely clear, so some helper functions (and confining in a library of sorts) are probably needed.

Edit: I just made a change to the ServiceLocator code; one can now write:

    var dc = ServiceLocator.GetInstanceOf<string, DataContext>("connectionString");  

This is the overload for one argument:

    public static T GetInstanceOf<T1, T>(T1 arg1) where T : class  
      return GetInstanceOf<Func<T1, T>>()(arg1);  

I only have 3 overloads (up to Func<T1, T2, T3, T>) but that should be enough for anything I might need in the foreseeable future. Oh, and I can still have / use the initial binding too (the one with no connection string). Cool :)

No comments: