1

I am following this CQS tuturiol https://github.com/Code-First/CQS-Sample and it uses Ninject.

I currently am using Unity and trying to convert this:

    Bind<IQueryFactory>().ToMethod(t => new QueryFactory(x => Container.Current.Resolve(x))).InTransientScope();

MY query factory is shown below:

public class QueryFactory : IQueryFactory
{
    private readonly Func<Type, object> _resolveCallback;

    public QueryFactory(Func<Type, object> resolveCallback)
    {
        _resolveCallback = resolveCallback;
    }

    public T ResolveQuery<T>()
        where T : class, IQuery
    {
        return _resolveCallback(typeof (T)) as T;
    }
}

I have tried container.RegisterType<IQueryFactory>(t => new InjectionFactory(u => u.Resolve(u))); but that doesnt work.

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Lemex
  • 3,772
  • 14
  • 53
  • 87
  • 2
    The query model given by that article is limiting, because the `IQuery` interface isn't generic. I would advice a model as explained [here](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92). – Steven Jul 14 '15 at 11:36

1 Answers1

3

You'd think that an InjectionFactory would be the way to go. This compiles:

container.RegisterType<IQueryFactory>(new ContainerControlledLifetimeManager(),
    new InjectionFactory((c, x, o) => new QueryFactory(t => c.Resolve(x))));

The problem is that the type x is always IQueryFactory so that doesn't get the results you want which is to return an IQuery.

Unfortunately, I don't think the current design fits with Unity very well.

However, with some slight modifications you can get the factory working. There are a few different ways of doing this (e.g. you could inject the container in the factory and resolve from there) however in this example I'll use a dictionary.

First we change the factory definition:

public class QueryFactory : IQueryFactory
{
    private readonly IDictionary<Type, Func<IQuery>> _factoryQueries;

    public QueryFactory(IDictionary<Type, Func<IQuery>> factoryQueries)
    {
        this._factoryQueries = factoryQueries;
    }

    public T ResolveQuery<T>() where T : class, IQuery
    {
        return this._factoryQueries[typeof(T)]() as T;
    }

Basically, the Func<Type, object> resolveCallback is swapped for an IDictionary containing Funcs for creating all supported IQuery types.

Next register the IDictionary and the IQueryFactory:

IUnityContainer container = new UnityContainer();

// Register all IQuery's
container.RegisterType<IActiveUsersQuery, ActiveUsersQuery>();
container.RegisterType<IUserByEmailQuery, UserByEmailQuery>();

IDictionary<Type, Func<IQuery>> factoryQueries = new Dictionary<Type, Func<IQuery>>()
{
    { typeof(IActiveUsersQuery), () => container.Resolve<IActiveUsersQuery>() },
    { typeof(IUserByEmailQuery), () => container.Resolve<IUserByEmailQuery>() },
};

// Register mapping
container.RegisterInstance<IDictionary<Type, Func<IQuery>>>(factoryQueries);
container.RegisterType<IQueryFactory, QueryFactory>();

var factory = container.Resolve<IQueryFactory>();

factory.ResolveQuery<IActiveUsersQuery>().Execute();
factory.ResolveQuery<IActiveUsersQuery>().Execute();

As mentioned, a simpler QueryFactory approach that takes a dependency on the container is:

public class QueryFactory : IQueryFactory
{
    private readonly IUnityContainer container;

    public QueryFactory(IUnityContainer container)
    {
        this.container = container;
    }

    public T ResolveQuery<T>()
        where T : class, IQuery
    {
        return this.container.Resolve(typeof(T)) as T;
    }
}

However, some would object to having the factory depend on the container implementation.

Another approach would be to get rid of the factory approach and inject the queries directly; this would make the dependencies obvious but I can see the scenario where you would want to dynamically get a query based on the command type. Also, I've seen relations between commands and queries which could be handled with open generics resolved in the composition root.

Randy Levy
  • 22,566
  • 4
  • 68
  • 94