ASP.NET 核心依赖项注入:使用 Func 委托在运行时解析的服务
本文关键字:运行时 服务 Func 依赖 核心 NET 注入 使用 ASP | 更新日期: 2023-09-27 17:56:34
我正在尝试向我的控制器注入服务,但我想根据几个参数注入服务的不同实例。实际上,对于这部分,它正在工作,我能够做到。
我想要的是根据我们从配置文件中获得的一些配置并遵守 DRY 规则加载特定的IRepository<Database>
实例(不要重复自己)。
我有这2节课:
public abstract class FooServicesProvider
{
public Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider =>
{
return null;
};
}
public class FooFileSystemServicesProvider : FooServicesProvider
{
public new Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider =>
{
//Specific code determining which database to use and create a new one if needed
//our databases are FOLDERS containing some files
//knowing how chosenDb.FullName is set is not important here
//[...]
var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName);
databaseRepository.testProperty = "Foo value";
return databaseRepository;
};
}
请注意用于重新定义 Func 代码的新关键字。这是我发现的最好的方法,因为 Func 委托,我非常有限,我不能在接口中使用它,也不能覆盖它。
现在在启动中的配置服务方法中.cs我有此代码
var fakeConfiguration = "File";
FooServicesProvider servicesProvider = null;
if(fakeConfiguration == "File")
{
servicesProvider = new FooFileSystemServicesProvider();
}
else
{
servicesProvider = new AnotherFooServicesProvider();
}
//Here is the tricky part
//This should call FooFileSystemServicesProvider.DatabaseRepository because of the "new" keyword, but it's NOT
services.AddScoped<IRepository<Database>>(servicesProvider.DatabaseRepository);
我的问题是 new 关键字在运行时被忽略,执行的 Func 是在我的基类中声明的关键字,而不是派生的关键字。
如果我这样做,它就可以工作
services.AddScoped<IRepository<Database>>((servicesProvider as FooFileSystemServicesProvider).DatabaseRepository);
但我不想投射它,因为我不知道我的服务提供商最终会是哪种类型。
我试图获取我的 servicesProvider 的类型并用它自己的类型强制转换它,但我收到编译器错误,因为 Type 变量和类是不同的。
那么如何在运行时执行好的 Func呢?谢谢
好的,所以我终于设法做了我想做的事,这实际上并不难,我的主要问题是处理我的 Func 不是一个方法而是一个委托的事实。我不习惯处理这种变量类型。
我在 Startup.cs 中的代码保持不变,但这是我的自定义服务提供商的新代码
public abstract class FooServicesProvider
{
public Func<IServiceProvider, IRepository<Database>> DatabaseRepository { get; protected set; }
}
public class FooFileSystemServicesProvider : FooServicesProvider
{
public FooFileSystemServicesProvider()
{
base.DatabaseRepository = GetDatabaseRepository;
}
private DatabaseFileSystemRepository GetDatabaseRepository(IServiceProvider serviceProvider)
{
//Specific code determining which database to use and create a new one if needed
//our databases are FOLDERS containing some files
//knowing how chosenDb.FullName is set is not important here
//[...]
var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName);
databaseRepository.testProperty = "Foo value";
return databaseRepository;
}
}
以防万一人们想知道:DatabaseFileSystemRepository
是一个实现接口IRepository<Database>>
的类
如果有人想出不同的解决方案,我很想知道。