В последнее время мы прекращаем использовать Autofa c и начинаем использовать Microsoft DependencyInjection в наших веб-и консольных приложениях netcore3.1. Мы по-прежнему любим, что они оба могли бы достичь 1043 * нашего развязанного дизайна. Просто простое решение использовать нативный пакет Microsoft , если он может делать то же самое со сторонними пакетами. Вот коды, которые мы пытаемся перенести, суть в том, что мы уже получаем преимущества, регистрируя типы из сканирующих сборок , и мы надеемся сохранить этот дизайн для снижения стоимости миграции,
RequiredServices .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 { }
ServiceModule.cs
Старый (мигрировать из): устаревший контейнерный конструктор от Autofa c
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();
}
ServiceCollectionExtension.cs
Новое (переход на): дескрипторы службы IServiceCollection от Microsoft.Extensions.DependencyInjection
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;
}
Startup.cs
Итак, наконец, мы можно добавить только одну строку в Startup.cs для регистрации типов из текущих сборок.
public void ConfigureServices(IServiceCollection services)
{
// Other DI
// ...
// Our core DAL services DI
services.RegisterAssemblyTypes<IRepository>(ServiceLifetime.Transient);
}
Нужно ли что-то еще, чтобы мы были осторожнее с этим переносом? Спасибо за любую рекомендацию или документацию.