4
votes

I have the following configuration in Simple Injector:

c.Register<IQueryable<Entity1>>(() => c.GetInstance<IDomainQueryFactory>().Query<Entity1>());
c.Register<IQueryable<Entity2>>(() => c.GetInstance<IDomainQueryFactory>().Query<Entity2>());
c.Register<IQueryable<Entity3>>(() => c.GetInstance<IDomainQueryFactory>().Query<Entity3>());
c.Register<IQueryable<Entity4>>(() => c.GetInstance<IDomainQueryFactory>().Query<Entity4>());
...

The IDomainQueryFactory factory is responsible for creating the instances of IQueryable<TEntity>. Some class (like MVC controller) then declares dependency only on IQueryable<Entity1>.

I am wondering if there is some way of writing these registrations with a single command.

1

1 Answers

5
votes

There is no way to do this, because Simple Injector favors composition using types over functional composition. This means that Simple Injector does not easily allow you to register a generic method to be used in the registration process, just as you would be able to use a generic type.

So to reduce the amount of boilerplate code and prevent having to update the configuration on each new entity, you will have to create a generic IQueryable<T> implementation and register that. This is how this implementation would look like:

public sealed class DomainQueryFactoryQueryable<T> : IQueryable<T>
{
    private readonly IDomainQueryFactory factory;

    public DomainQueryFactoryQueryable(IDomainQueryFactory factory) {
        this.factory = factory;
    }

    public Type ElementType { get { return this.GetQuery().ElementType; } }
    public Expression Expression { get { return this.GetQuery().Expression; } }
    public IQueryProvider Provider { get { return this.GetQuery().Provider; } }

    public IEnumerator<T> GetEnumerator() {
        return this.GetQuery().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return this.GetEnumerator();
    }

    private IQueryable<T> GetQuery() { 
        return this.factory.Query<T>();
    }
}

And you can register this as follows:

container.RegisterOpenGeneric(typeof(IQueryable<>), typeof(DomainQueryFactoryQueryable<>));