pFrenchie
pFrenchie

Reputation: 377

Implement Lazy Proxy in Simple Injector

The Simple Injector docs describe how to implement a lazy dependency. However, this example only covers registering a simple interface (IMyService). How would this work with an open generic (EG. IMyService<T>)?

Here's my existing registration:

container.Register(typeof(IDbRepository<>), typeof(DbRepository<>));

Obviously the following code doesn't compile as I'm not specifying the generic type:

container.Register(typeof(IDbRepository<>),
    () => new LazyDbRepositoryProxy<>(new Lazy<IDbRepository<>(container.GetInstance<>)));

Is this possible in Simple Injector? I can only see the following overrides for Register, non of which allow a func / instanceCreator to be passed in:

public void Register(Type openGenericServiceType, params Assembly[] assemblies);
public void Register(Type openGenericServiceType, IEnumerable<Assembly> assemblies);
public void Register(Type openGenericServiceType, Assembly assembly, Lifestyle lifestyle);
public void Register(Type openGenericServiceType, IEnumerable<Assembly> assemblies, Lifestyle);
public void Register(Type openGenericServiceType, IEnumerable<Type> implementationTypes, Lifestyle);
public void Register(Type openGenericServiceType, IEnumerable<Type> implementationTypes);

Upvotes: 1

Views: 301

Answers (1)

Steven
Steven

Reputation: 172606

A code construct such as you suggested is not one you can express in C#. But by making a small change to your design, you can elegantly solve your problem.

The trick is to inject Container into your LazyDbRepositoryProxy<T>. This way, Simple Injector can easily construct new LazyDbRepositoryProxy<T> instances using auto-wiring which prevents you from having to register a delegate (which won't work for open-generic types).

So change your LazyDbRepositoryProxy<T> to the following:

// As this type depends on your DI library, you should place this type inside your
// Composition Root.
public class LazyDbRepositoryProxy<T> : IDbRepository<T>
{
    private readonly Lazy<DbRepository<T>> wrapped;

    public LazyDbRepositoryProxy(Container container)
    {
        this.wrapped = new Lazy<IMyService>(container.GetInstance<DbRepository<T>>));
    }
}

And register your types as follows:

container.Register(typeof(DbRepository<>));
container.Register(typeof(IDbRepository<>), typeof(LazyDbRepositoryProxy<>));

Upvotes: 1

Related Questions