Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET内核中的依赖项注入_C#_Dependency Injection_Asp.net Core - Fatal编程技术网

C# ASP.NET内核中的依赖项注入

C# ASP.NET内核中的依赖项注入,c#,dependency-injection,asp.net-core,C#,Dependency Injection,Asp.net Core,在Autofac中,您可以使用RegisterAssemblyTypes注册依赖项 因此,您将能够执行类似的操作,是否有一种方法可以在的内置DI中执行类似的操作 builder.RegisterAssemblyTypes(Assembly.Load("SomeProject.Data")) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces() .InstancePerLifetim

在Autofac中,您可以使用RegisterAssemblyTypes注册依赖项 因此,您将能够执行类似的操作,是否有一种方法可以在
的内置
DI
中执行类似的操作

builder.RegisterAssemblyTypes(Assembly.Load("SomeProject.Data"))
    .Where(t => t.Name.EndsWith("Repository"))
    .AsImplementedInterfaces()
    .InstancePerLifetimeScope();
这就是我想要注册的

LeadService.cs

LeadTransDetailRepository.cs

公共类LeadTransDetailRepository:RepositoryBase,
ILeadTransDetailRepository
{
公共LeadTransDetailRepository(IDatabaseFactory数据库工厂)
:base(数据库工厂){}
}
公共接口ILeadTransDetailRepository:IRepository{}
这就是我当时试图注册的方式,但我不知道如何注册存储库 Startup.cs

public void配置服务(IServiceCollection服务)
{
//添加框架服务。
services.AddMvc();
services.AddTransient();
//不知道如何注册存储库
添加(新的ServiceDescriptor(typeof(ILeadTransDetailRepository)),
typeof(IRepository),ServiceLifetime.Transient);
添加(新的ServiceDescriptor)(类型为(IDatabaseFactory),
typeof(DatabaseFactory),ServiceLifetime.Transient);
services.AddTransient(=>newdatacontext(
配置[“数据:默认连接:ConnectionString”]);
}

使用ASP.NET核心依赖项注入/IoC容器没有现成的方法,但它是“按设计”实现的

ASP.NET IoC容器/DI是一种添加DI功能的简单方法,可作为其他IoC容器框架构建到ASP.NET核心应用程序中的基础

这就是说,它支持简单的场景(注册,尝试使用第一个构造函数和大多数参数来满足依赖项和作用域依赖项),但它缺乏自动注册或装饰器支持等高级场景


对于此功能,您必须使用第三方库和/或第三方IoC容器(AutoFac、StructureMap等)。它们仍然可以插入
IServiceCollection
您以前的注册仍然有效,但您可以在其上获得其他功能

ASP.NET核心从头设计,以支持和利用依赖注入

ASP.NET核心应用程序可以通过将内置框架服务注入Startup类中的方法来利用这些服务,应用程序服务也可以配置为注入

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

不打算替换其他容器

资料来源:


默认的ASP.NET容器是

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

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

Autofac()是一个已经可用于ASP.NET Core的工具,您可以通过引用

Autofac和

Autofac.Extensions.DependencyInjection软件包


资料来源:

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

public static void ResolveAllTypes(此IServiceCollection服务、字符串解决方案前缀、参数字符串[]项目后缀)
{
//solutionPrefix是我的解决方案名称,用于与Microsoft的其他程序集分离,。。。
//ProjectSuffix是我要扫描和注册的项目
//注意:要使用此代码,您必须将您的项目引用到“ProjectSuffix”项目。
var allAssemblies=新列表();
var path=path.GetDirectoryName(Assembly.getExecutionGassembly().Location);
foreach(目录.GetFiles(路径“*.dll”)中的var dll)
allAssemblies.Add(Assembly.LoadFile(dll));
变量类型=新列表();
foreach(所有组件中的var组件)
{
if(assembly.FullName.StartsWith(solutionPrefix))
{
foreach(程序集中的变量assemblyDefinedType.DefinedTypes)
{
if(projectsuffix.Any(x=>assemblyDefinedType.Name.EndsWith(x)))
{
Add(assemblyDefinedType.AsType());
}
}
}
}
var implementTypes=types.Where(x=>x.IsClass.ToList();
foreach(implementTypes中的var implementType)
{
//我默认“AService”总是实现“IAService”,您可以自定义它
var interfaceType=implementType.GetInterface(“I”+implementType.Name);
if(interfaceType!=null)
{
添加(新的ServiceDescriptor(interfaceType、implementType、,
ServiceLifetime.Scoped);
}
}
}

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

只需添加nuget软件包
SharpDiAutoRegister
,并在ConfigureServices方法中添加约定:

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

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

//and so on...

是的,我看到我可以使用Autofac,我通常使用它,只是想我会试试内置的。你提到的第三方LIB已经过时很久了,所以我想它们会有更多的功能。正如我所说的,它的设计缺乏这些功能,据我所知,也没有计划添加它们,至少在自动注册/组装扫描方面。自动布线代码很容易自己实现。只需要一些反射代码和您自己的扩展方法。Autofac i
public class LeadTransDetailRepository : RepositoryBase<LeadTransDetail>, 
    ILeadTransDetailRepository
{
    public LeadTransDetailRepository(IDatabaseFactory databaseFactory) 
        : base(databaseFactory) { }
}

public interface ILeadTransDetailRepository : IRepository<LeadTransDetail> { }
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"]));
}
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));
                }

            }

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

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

//and so on...