.NET 依赖注入与通用接口和继承

问题描述 投票:0回答:1

我最近想到了一个案例,我可以将新闻导入器的抽象构建到 .NET DI Contianer 中。

这是我的示例案例。

此类代表新闻源。

public abstract class Source {
   public Guid Id {get; set;}
}

这个具体来源是一个 Rss Feed。

public class RssFeed: Source {
   public string Url {get; set;}
}

现在我为某些来源的进口商提供了一个通用界面。

public interface ISourceImporter<TSource> where TSource:  Source {
Task IEnumerable<Post> ImportAsync(TSource source)
}

以及 RssFeed 源的具体实现

public class RssFeedImporter: ISourceImporter<RssFeed> {
}

将服务注册到 DI 容器中

services.AddSingleton<ISourceImporter<RssFeed>, RssFeedImporter>()

所以主要问题出现在通过ServiceProvider使用服务时。我的命令我想像这样抽象我的源的具体类型。

public Task ImportCommand(Source source) {
   ISourceImporter<Source> importer = (ISourceImport<Source>)serviceProvider
           .GetRequiredService(typeof(ISourceImporter<>).MakeGenericType(source.GetType()))

   var posts = await importer.ImportAsync(source);
}

有没有办法使用 .NET 依赖容器构建该抽象?也许我的结构不适合这个? 我读了一篇关于开放泛型的文章,但这在构建 DI 容器时给我带来了循环依赖。

感谢您的帮助。

c# .net inheritance dependency-injection composition
1个回答
0
投票

您的方法是正确的,但是您面临着在运行时解析开放泛型的问题。但是,有一种方法可以结合使用反射和工厂模式来实现您的目标。

定义工厂接口:创建一个工厂接口,提供根据Source的具体类型创建ISourceImporter实例的方法。

实现工厂:使用反射实现工厂接口,根据Source的具体类型动态解析合适的ISourceImporter实现。

注册工厂:在DI容器中注册工厂。

使用工厂:在您的命令中或任何需要导入新闻的地方,从 DI 容器解析工厂并使用它为给定源创建适当的导入器。

这是一个示例实现:

public interface ISourceImporterFactory
{
    ISourceImporter<Source> CreateImporter(Source source);
}

public class SourceImporterFactory : ISourceImporterFactory
{
    private readonly IServiceProvider _serviceProvider;

    public SourceImporterFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ISourceImporter<Source> CreateImporter(Source source)
    {
        Type importerType = typeof(ISourceImporter<>).MakeGenericType(source.GetType());
        dynamic importer = _serviceProvider.GetRequiredService(importerType);
        return importer;
    }
}

// Register the factory in the DI container
services.AddSingleton<ISourceImporterFactory, SourceImporterFactory>();

// Usage in your command or wherever you need to import news
public async Task ImportCommand(Source source)
{
    var importerFactory = serviceProvider.GetRequiredService<ISourceImporterFactory>();
    var importer = importerFactory.CreateImporter(source);
    var posts = await importer.ImportAsync(source);
}

这样,您就可以动态解析给定源类型的适当导入器,而无需开放泛型,也不会在 DI 容器注册期间遇到循环依赖问题。

© www.soinside.com 2019 - 2024. All rights reserved.