【问题标题】:ASP.NET Core dependency injection: Service resolved at runtime using a Func delegateASP.NET Core 依赖注入:使用 Func 委托在运行时解析服务
【发布时间】:2016-07-12 08:54:04
【问题描述】:

我正在尝试向我的控制器注入服务,但我想根据几个参数注入不同的服务实例。实际上对于这部分它正在工作,我能够做到。

我想要的是根据我们从配置文件中获得的一些配置并遵守 DRY 规则(不要重复自己)来加载 IRepository<Database> 的特定实例。

我有这两个类:

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 代码的 new 关键字。这是我发现的最好方法,因为 Func 委托,我非常有限,我不能在接口中使用它,也不能覆盖它。

现在在我的 Startup.cs 中的 ConfigureServices 方法中,我有这段代码

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 最终会是哪种类型。

我尝试获取我的 servicesProvider 的类型并将其转换为自己的类型,但由于 Type 变量和 Class 不同,因此出现编译器错误。

那么我怎样才能在运行时执行良好的 Func 呢?谢谢

【问题讨论】:

  • 您将必须创建基类virtualDatabaseRepository,并在派生类型中使用override
  • 在您的委托属性声明中通过覆盖替换新关键字。有用吗?
  • 当然new 关键字被忽略了,因为new 只隐藏了基类的方法/属性,不会替换或覆盖它...
  • 正如我所说,我不能覆盖 DatabaseRepository,因为我的 Func 是一个委托而不是一个方法,因此它被视为一个属性。
  • @Tseng 您评论的后半部分和您对我的问题的否决在这里都没有用处。我被卡住了,因为基本上我想要的是“覆盖Func 类型的属性”,我所有的尝试都失败了,这就是我想出new 关键字的原因。我读过几次它隐藏基类属性,但我确实误解了这个词。所以我不认为我的问题缺乏研究,这只是一个不理解。

标签: c# dependency-injection runtime asp.net-core func


【解决方案1】:

好的,所以我终于设法做我想做的事,实际上并不难,我的主要问题是处理我的 Func 不是方法而是委托的事实。我不习惯处理这种变量类型。

我在 Startup.cs 中的代码保持不变,但这是我的自定义 ServicesProvider 的新代码

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&lt;Database&gt;&gt; 的类

如果有人提出不同的解决方案,我很想知道。

【讨论】:

    猜你喜欢
    • 2018-08-23
    • 2022-12-20
    • 2020-09-15
    • 1970-01-01
    • 2019-06-22
    • 2019-07-09
    • 2017-04-15
    相关资源
    最近更新 更多