Reputation: 770
Within my Solution I have multiple Projetcs that define an EntityFramework Core DbContext
. In my Entrypoint Project I would like to inject all instances of DbContext
to be able to apply pending migrations for each of them.
The contexts are registered through AddDbContext<T>(this IServiceCollection)
and are copied into the DryIoc using Populate(this IContainer, IServiceCollection)
class Base {};
class LeafOne : Base {};
class LeafTwo : Base {};
void Fun()
{
var container = new Container();
// Using Singleton to prove the point
// This is meant to be a simplified version of the `AddDbContext` calls
container.Register<LeafOne>(Reuse.Singleton);
container.Register<LeafTwo>(Reuse.Singleton);
container.ResolveMany<Base>(); // empty
}
How can I properly register the Base
to resolve both singleton instances?
Here is what I tried:
container.RegisterMapping<Base, LeafOne>();
container.RegisterMapping<Base, LeafTwo>();
container.ResolveMany<Base>(); // resolves only the LeafOne instance
container.Register<Base, LeafOne>(Reuse.Singleton);
container.Register<Base, LeafTwo>(Reuse.Singleton);
container.ResolveMany<Base>();
// resolves instances for both leaf classes, but -as expected-
// they are different instances than the ones registered in
// the beginning
container.RegisterDelegate<Base>(ctx => ctx.Resolve<LeafOne>());
container.RegisterDelegate<Base>(ctx => ctx.Resolve<LeafTwo>());
container.ResolveMany<Base>();
// actually works for this example, but won't for DbContext because
// its trying to call a parameterless constructor for `Base` on resolve
// which doesn't exist
Is there a simple way to alias a type for it's parent class?
Upvotes: 1
Views: 592
Reputation: 4950
The RegisterMapping
should work but it won't in the current DryIoc <=4.3.4
because RegisterMapping
uses the IfAlreadyRegistered.Keep
by default, keeping the first Base registration and rejecting the second.
Here is the issue to fix it.
Until then you need to register with the service keys - it maybe even better in your specific case because it will hide the Base
from the normal resolution but will keep them resolved or injected as a collection.
Here the code
using System;
using System.Linq;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.Register<LeafOne>(Reuse.Singleton);
container.Register<LeafTwo>(Reuse.Singleton);
// the keys are required in the DryIoc <=4.3.4 because RegisterMapping uses the IfAlreadyRegistered.Keep by default,
// keeping the first Base registration and rejecting the second
container.RegisterMapping<Base, LeafOne>(serviceKey: 1);
container.RegisterMapping<Base, LeafTwo>(serviceKey: 2);
var bases = container.ResolveMany<Base>().ToArray();
Console.WriteLine(bases.Length); // outputs 2
}
class Base {};
class LeafOne : Base {};
class LeafTwo : Base {};
}
This should work now:
using System;
using System.Linq;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.Register<LeafOne>(Reuse.Singleton);
container.Register<LeafTwo>(Reuse.Singleton);
// Works in DryIoc v4.4
container.RegisterMapping<Base, LeafOne>();
container.RegisterMapping<Base, LeafTwo>();
var bases = container.ResolveMany<Base>().ToArray();
Console.WriteLine(bases.Length); // outputs 2
}
class Base {};
class LeafOne : Base {};
class LeafTwo : Base {};
}
Upvotes: 2