在autofac和microsoft dependency-injection之间扫描装配体的注册类型。

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

最近,我们停止使用 自动传真,并开始使用 微软 在我们的netcore3.1的web和console应用中的DependencyInjection。我们还是很喜欢他们两个可以完成我们的解耦设计。只是一个简单的决定,使用原生的 微软 包,如果它能用第三方包做同样的事情。下面是我们尝试迁移的代码,重点是我们已经通过注册类型获得了好处,从 扫描组件我们希望保留这种设计,以降低迁移成本。

所需的Services.cs

在DI之前,为了防止注册爆炸(是的,我们确实有100多个接口和服务),我们不对每个服务进行注册,而是使用扫描组件。

public interface IRepository { } 
public interface IUserRepository: IRepository { }
public interface ITodoRepository: IRepository { }
// ...
public interface INum100Repository: IRepository { }

public abstract class RepositoryBase: IRepository { } 
public class UserRepository: RepositoryBase, IUserRepository { } 
public class TodoRepository: RepositoryBase, ITodoRepository { } 
// ...
public class Num100Repository: RepositoryBase, INum100Repository { } 

服务模块.cs

旧的(迁移自)。传统的Autofac容器构建器

protected override void Load(Autofac.ContainerBuilder builder)
{
    base.Load(builder);

    var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
    assemblies.SelectMany(x => x.GetReferencedAssemblies())
        .Where(t => false == assemblies.Any(a =>a.FullName == t.FullName))
        .Distinct()
        .ToList()
        .ForEach(x => assemblies.Add(AppDomain.CurrentDomain.Load(x)));
    var scanAssemblies = assemblies.ToArray();    

    // Core DAL services
    builder.RegisterAssemblyTypes(scanAssemblies)
        .PublicOnly()
        .Where(t => !t.IsInterface)
        .As<IRepository>()
        .AsImplementedInterfaces()
        .InstancePerDependency();
}               

服务收集扩展.cs

新(迁移到)。通过Microsoft.Extensions.DependencyInjection实现IServiceCollection服务描述符。

public static IServiceCollection RegisterAssemblyTypes<T>(this IServiceCollection services, ServiceLifetime lifetime, List<Func<TypeInfo, bool>> predicates = null)
{
    var scanAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
    scanAssemblies.SelectMany(x => x.GetReferencedAssemblies())
        .Where(t => false == scanAssemblies.Any(a => a.FullName == t.FullName))
        .Distinct()
        .ToList()
        .ForEach(x => scanAssemblies.Add(AppDomain.CurrentDomain.Load(x)));

    var interfaces = scanAssemblies
        .SelectMany(o => o.DefinedTypes
            .Where(x => x.IsInterface)
            .Where(x => x != typeof(T))
            .Where(x => typeof(T).IsAssignableFrom(x))
        );

    foreach (var @interface in interfaces)
    {
        var types = scanAssemblies
            .SelectMany(o => o.DefinedTypes
                .Where(x => x.IsClass)
                .Where(x => @interface.IsAssignableFrom(x))
            );

        if (predicates?.Count() > 0)
        {
            foreach (var predict in predicates)
            {
                types = types.Where(predict);
            }
        }

        foreach (var type in types)
        {
            services.TryAdd(new ServiceDescriptor(
                @interface,
                type,
                lifetime)
            );
        }
    }

    return services;
}

启动.cs

所以,最后我们只需在 启动.cs 来注册当前程序集的类型。

public void ConfigureServices(IServiceCollection services)
{
    // Other DI
    // ...

    // Our core DAL services DI
    services.RegisterAssemblyTypes<IRepository>(ServiceLifetime.Transient);
}    

对于这种迁移的东西,我们还有什么需要注意的吗?感谢任何建议或文档。

c# asp.net-core dependency-injection autofac
1个回答
0
投票

我的意思是在评论下的问题是。

考虑到你有服务类型和实现类型。

interface IService1 { }
interface IService2 { }

class Service : IService1, IService2
{ }

Autofac注册码。

var containerBuilder = new ContainerBuilder();

containerBuilder.RegisterType<Service>()
    .AsImplementedInterfaces()
    // When you use lifetime
    .SingleInstance();

var autofacContainer = containerBuilder.Build();

微软扩展DI注册码(类似于你得到的)。

var serviceCollection = new ServiceCollection();

serviceCollection.TryAddSingleton<IService1, Service>();
serviceCollection.TryAddSingleton<IService2, Service>();

var serviceProvider = serviceCollection.BuildServiceProvider();

如果你解决服务类型。

// Autofac
var obj1 = autofacContainer.Resolve<IService1>();
var obj2 = autofacContainer.Resolve<IService2>();

// autofacResult = true
var autofacResult = object.ReferenceEquals(obj1, obj2);

// MS DI
var obj3 = serviceProvider.GetRequiredService<IService1>();
var obj4 = serviceProvider.GetRequiredService<IService2>();

// serviceProviderResult = false
var serviceProviderResult = object.ReferenceEquals(obj3, obj4);

这是因为Autofac将提供的类型注册为单人,并将所有服务类型注册为实现,而MS DI将服务实现类型对注册为单人。

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