【问题标题】:Dependency Injection in ASP.NET CoreASP.NET Core 中的依赖注入
【发布时间】:2016-04-16 08:51:49
【问题描述】:

在 Autofac 中,您可以使用 RegisterAssemblyTypes 注册您的依赖项 所以你将能够做这样的事情,有没有办法在DI for .net Core 的构建中做类似的事情

builder.RegisterAssemblyTypes(Assembly.Load("SomeProject.Data"))
    .Where(t => t.Name.EndsWith("Repository"))
    .AsImplementedInterfaces()
    .InstancePerLifetimeScope();

这就是我要注册的内容

LeadService.cs

public class LeadService : ILeadService
{
    private readonly ILeadTransDetailRepository _leadTransDetailRepository;

    public LeadService(ILeadTransDetailRepository leadTransDetailRepository)
    {
        _leadTransDetailRepository = leadTransDetailRepository;
    }
}

LeadTransDetailRepository.cs

public class LeadTransDetailRepository : RepositoryBase<LeadTransDetail>, 
    ILeadTransDetailRepository
{
    public LeadTransDetailRepository(IDatabaseFactory databaseFactory) 
        : base(databaseFactory) { }
}

public interface ILeadTransDetailRepository : IRepository<LeadTransDetail> { }

这就是我当时尝试注册的方式,但我不知道如何注册存储库 Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddTransient<ILeadService, LeadService>();

    //not sure how to register the repositories
    services.Add(new ServiceDescriptor(typeof(ILeadTransDetailRepository),
        typeof(IRepository<>), ServiceLifetime.Transient));

    services.Add(new ServiceDescriptor(typeof(IDatabaseFactory),
        typeof(DatabaseFactory), ServiceLifetime.Transient));
    services.AddTransient<DbContext>(_ => new DataContext(
        this.Configuration["Data:DefaultConnection:ConnectionString"]));
}

【问题讨论】:

  • 自动布线代码很容易自己实现。所需要的只是一些反射代码和您自己的扩展方法。 Autofac 是开源的,你可以看看你感兴趣的方法是如何实现的,然后自己添加到 MVC Core 中。

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


【解决方案1】:

使用 ASP.NET Core 依赖注入/IoC 容器没有开箱即用的方法,但它是“设计使然”。

ASP.NET IoC 容器/DI 旨在成为一种添加 DI 功能的简单方法,并作为其他 IoC 容器框架构建到 ASP.NET Core 应用程序的基础。

话虽如此,它支持简单的场景(注册,尝试使用具有大多数参数的第一个构造函数来满足依赖关系和作用域依赖关系),但它缺乏自动注册或装饰器支持等高级场景。

对于此功能,您必须使用第 3 方库和/或第 3 方 IoC 容器(AutoFac、StructureMap 等)。它们仍然可以插入IServiceCollection,您之前的注册仍然可以使用,但您可以获得额外的功能。

【讨论】:

  • 是的,我看到我可以使用 Autofac,我通常使用它,只是认为不适合尝试内置。你提到的第 3 方库已经发布了更长的时间,所以我猜他们会有更多的功能。
  • 正如我所说,它缺乏这些功能是设计使然,据我所知,也没有添加它们的计划,至少对于自动注册/装配扫描而言。
【解决方案2】:

我认为您可以通过手动扫描注册所有服务。然后将它们注册到服务集合。这是我的示例代码(.Net core 2.0)

public static void ResolveAllTypes(this IServiceCollection services, string solutionPrefix, params string[] projectSuffixes)
        {
            //solutionPrefix is my Solution name, to separate with another assemblies of Microsoft,...
            //projectSuffixes is my project what i want to scan and register
            //Note: To use this code u must reference your project to "projectSuffixes" projects.

            var allAssemblies = new List<Assembly>();
            var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            foreach (var dll in Directory.GetFiles(path, "*.dll"))
                allAssemblies.Add(Assembly.LoadFile(dll));


            var types = new List<Type>();
            foreach (var assembly in allAssemblies)
            {
                if (assembly.FullName.StartsWith(solutionPrefix))
                {
                    foreach (var assemblyDefinedType in assembly.DefinedTypes)
                    {
                        if (projectSuffixes.Any(x => assemblyDefinedType.Name.EndsWith(x)))
                        {
                            types.Add(assemblyDefinedType.AsType());

                        }
                    }
                }
            }

            var implementTypes = types.Where(x => x.IsClass).ToList();
            foreach (var implementType in implementTypes)
            {
                //I default "AService" always implement "IAService", You can custom it
                var interfaceType = implementType.GetInterface("I" + implementType.Name);

                if (interfaceType != null)
                {
                    services.Add(new ServiceDescriptor(interfaceType, implementType,
                        ServiceLifetime.Scoped));
                }

            }

        }

【讨论】:

  • 这就是我最终这样做的方式。我将更新我的问题并添加我的解决方案。谢谢
  • 我认为当你有一个大项目和大团队要管理时,这不是合适的方法,而且它是紧密耦合的。
  • 是的!代码这么快。在大项目中我们会做得更专业。
【解决方案3】:

我也想尝试一下内置,对缺少自动注册感到恼火,并为此构建了一个开源项目,看看:

https://github.com/SharpTools/SharpDiAutoRegister

只需添加 nuget 包 SharpDiAutoRegister 并在 ConfigureServices 方法中添加您的约定:

services.ForInterfacesMatching("^I[a-zA-z]+Repository$")
        .OfAssemblies(Assembly.GetExecutingAssembly())
        .AddSingletons();

services.ForInterfacesMatching("^IRepository")
        .OfAssemblies(Assembly.GetExecutingAssembly())
        .AddTransients();

//and so on...

【讨论】:

    【解决方案4】:

    ASP.NET Core 的设计初衷就是支持和利用依赖注入。

    ASP.NET Core 应用程序可以通过将内置框架服务注入到 Startup 类的方法中来利用它们,并且应用程序服务也可以配置为进行注入。

    ASP.NET Core 提供的默认服务容器提供了一个最小的功能集并且是

    不打算替换其他容器。

    来源:https://docs.asp.net/en/latest/fundamentals/dependency-injection.html


    默认的 ASP.NET 容器是

    简单且不提供强大的配置和性能 其他容器可用的选项。

    幸运的是,您可以将默认容器替换为社区创建的功能齐全的容器之一,该容器已作为 NuGet 包提供。

    Autofac (http://autofac.org/ ) 是已经可用于 ASP.NET Core 的一种,您可以通过引用这两个文件将其添加到您的项目中

    Autofac 和

    Autofac.Extensions.DependencyInjection 包。

    来源:https://blogs.msdn.microsoft.com/webdev/2016/03/28/dependency-injection-in-asp-net-core/

    【讨论】:

      猜你喜欢
      • 2018-01-16
      • 2019-02-22
      • 1970-01-01
      • 2017-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多