I am writing some integration tests where I test implementations of a particular interface, IQueryMapping<TSource, TDest>
. This interface exists to map from an IQueryable<TSource>
to an IQueryable<TDest>
. I want to make sure that they do
not throw exceptions when compiling a query using Entity Framework.
I am lazy and I don't want to have to update my tests every time I create a new mapping! All I want to do is ensure that every mapping which is used by my application will pass the test. I can bootstrap my container and then find all implementations that are registered with it like so:
from r in Container.GetCurrentRegistrations()
let t = r.ServiceType
where t.IsGenericType && t.GetGenericTypeDefinition() == typeof (IQueryMapping<,>)
select r.GetInstance()
So far, so good!
Alongside my concrete implementations, I have a default open generic mapper which performs basic automatic property mapping (remember, I am lazy and don't want to do this manually!)
container.RegisterOpenGeneric(typeof(IQueryMapping<,>), typeof(DefaultAutoMapping<,>));
Unfortunately, open generics don't seem to appear in Container.GetCurrentRegistrations()
call. From the docs:
Returns an array with the current registrations. This list contains all explicitly registered types, and all implicitly registered instances. Implicit registrations are all concrete unregistered types that have been requested, all types that have been resolved using unregistered type resolution (using the ResolveUnregisteredType event), and requested unregistered collections. Note that the result of this method may change over time, because of these implicit registrations.
What I'd really like is for Simple Injector to tell me about every requested occurrence of IQueryMapping<,>
in all registered components.
For example, if I have left IQueryMapping<Foo, Bar>
as an open generic DefaultAutoMapping<,>
and a registered component has the constructor signature
public MyComponent(IQueryMapping<Foo, Bar> mapping)
{
...
}
I would like the container to tell me about this specialised IQueryMapping<,>
, so that I can request an instance of it and run it through my test.
A call to RegisterOpenGeneric
will in the background hook a delegate onto the ResolveUnregisteredType
event. This basically means that the container itself is completely unaware of the registration, and the registration will only get added when a closed-generic version of the registered abstraction is requested; either directly using a call to GetInstance()
or indirectly because a type that depends on that abstraction is resolved.
The trick here is to call Verify()
before calling GetCurrentRegistrations()
. A call to Verify()
will cause the container to build all expression trees, compile all delegates, and create all instances of all registrations that are known to the container. This will force the container to add the registrations of each found closed-generic version of that open-generic abstraction.
Long story short: call Verify()
first.