views:

141

answers:

2

Consider this code snippet:

public static class ApplicationContext
{
    private static Func<TService> Uninitialized<TService>()
    {
        throw new InvalidOperationException();
    }

    public static Func<IAuthenticationProvider> AuthenticationProvider = Uninitialized<IAuthenticationProvider>();
    public static Func<IUnitOfWorkFactory> UnitOfWorkFactory = Uninitialized<IUnitOfWorkFactory>();
}

//can also be in global.asax if used in a web app.
public static void Main(string[] args) 
{
    ApplicationContext.AuthenticationProvider = () => new LdapAuthenticationProvider();
    ApplicationContext.UnitOfWorkFactory = () => new EFUnitOfWorkFactory();
}

//somewhere in the code.. say an ASP.NET MVC controller
ApplicationContext.AuthenticationProvider().SignIn(username, true);

Are delegates in the static class ApplicationContext thread-safe in the sense that multiple-threads can invoke them?

What potential problems will I face if I pursue this approach?

+3  A: 

Are delegates in the static class ApplicationContext thread-safe in the sense that multiple-threads can invoke them?

Yes. But a delegate is only as thread-safe as the method it points to.

So, if the methods called by your AuthenticationProvider and UnitOfWorkFactory delegates are thread-safe, then so will your delegates be.

In the code you've provided, these are simply constructor calls. It doesn't really get much more thread-safe than that (unless you've got some crazy threading logic in your constructors -- I certainly hope not).

What potential problems will I face if I pursue this approach?

None that result directly from invoking your delegates. Again, the only concerns regarding thread-safety that you should be worried about are those that pertain to the actual methods called by your delegates (in this case, the constructors for LdapAuthenticationProvider and EFUnitOfWorkFactory).

UPDATE: limpalex made a good observation: in the code you've posted, you are actually calling the Uninitialized<TService> method in the static constructor for your ApplicationContext class, which will throw an exception. What you want to do is assign your delegates to the method. I think what you're going for is something like this:

// note: changed return type to TService to match Func<TService> signature
private static TService Uninitialized<TService>()
{
    throw new InvalidOperationException();
}

// note: removed () symbols to perform assignment instead of method call
public static Func<IAuthenticationProvider> AuthenticationProvider = Uninitialized<IAuthenticationProvider>;
public static Func<IUnitOfWorkFactory> UnitOfWorkFactory = Uninitialized<IUnitOfWorkFactory>;
Dan Tao
+2  A: 

Your Uninitialized() function does not return a Func object that throws an exception, it just throws an exception. Cause this will happen in ApplicationContext static constructor, this type will become unusable. You should do smth like that "return () => throw new IOE(); "

limpalex
Good catch! Thanks a lot!
leypascua
Good find. Missed that one myself.
Dan Tao