使用 DryIoc 解析从基础 class 派生的服务
Resolve Services derived from base class using DryIoc
上下文
在我的解决方案中,我有多个定义 EntityFramework 核心 DbContext
的项目。在我的入口点项目中,我想注入 DbContext
的所有实例,以便能够为每个实例应用挂起的迁移。
上下文通过 AddDbContext<T>(this IServiceCollection)
注册并使用 Populate(this IContainer, IServiceCollection)
复制到 DryIoc
例子
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
}
问题
如何正确注册 Base
以解析两个单例实例?
这是我尝试过的:
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
有没有一种简单的方法可以为其父类型添加别名 class?
RegisterMapping
应该可以,但在当前的 DryIoc <=4.3.4 中不行
因为 RegisterMapping
默认使用 IfAlreadyRegistered.Keep
,保留第一个 Base 注册并拒绝第二个。
在那之前您需要使用服务密钥注册 - 在您的特定情况下可能更好 因为它会隐藏 Base
从正常分辨率但会将它们作为集合解析或注入。
这里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 {};
}
更新:DryIoc v4.4 发布,RegisterMapping 不需要服务密钥
现在应该可以工作了:
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 {};
}
上下文
在我的解决方案中,我有多个定义 EntityFramework 核心 DbContext
的项目。在我的入口点项目中,我想注入 DbContext
的所有实例,以便能够为每个实例应用挂起的迁移。
上下文通过 AddDbContext<T>(this IServiceCollection)
注册并使用 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
}
问题
如何正确注册 Base
以解析两个单例实例?
这是我尝试过的:
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
有没有一种简单的方法可以为其父类型添加别名 class?
RegisterMapping
应该可以,但在当前的 DryIoc <=4.3.4 中不行
因为 RegisterMapping
默认使用 IfAlreadyRegistered.Keep
,保留第一个 Base 注册并拒绝第二个。
在那之前您需要使用服务密钥注册 - 在您的特定情况下可能更好 因为它会隐藏 Base
从正常分辨率但会将它们作为集合解析或注入。
这里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 {};
}
更新:DryIoc v4.4 发布,RegisterMapping 不需要服务密钥
现在应该可以工作了:
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 {};
}