Open Jenausmax opened 2 years ago
Что такое DI? Это механизм, позволяющий сделать взаимодействующие в приложении объекты слабосвязанными. Эти объекты связаны между собой через абстракции, например, через интерфейсы. Это позволяет всей системе быть более гибкой, адаптируемой и расширяемой. Главным моментом данного механизма является зависимость - некоторая сущность, от которой зависит другая сущность.
Зачем использовать механизм DI? При использовании DI, например, при связывании двух классов. Мы можем использовать интерфейс, который будет использоваться в одном из классов, это снимает зависимость одного класса от другого. В интерфейсе будет использоваться абстрактный метод. И уже в классе будет вызываться объект этого интерфейса. Т.е. один из классов перестает зависеть от конкретной реализации другого.
Жизненный цикл зависимостей. Какие бывают. С точки зрения жизненного цикла сервисы(зависимости) могут представлять один из следующих типов: 1) Transient: при каждом обращении к сервису создается новый объект сервиса. В течении одного запроса может быть несколько обращений к сервису, соответственно при каждом обращении будет создаваться новый объект. Подобная модель жизненного цикла наиболее подходит для легковесных сервисов, которые не хранят данных о состоянии 2) Scoped: для каждого запроса создается свой объект сервиса. То есть если в течение одного запроса есть несколько обращений к одному сервису, то при всех этих обращениях будет использоваться один и тот же объект сервиса 3) Singleton: объект сервиса создается при первом обращении к нему, все последующие запросы используют один и тот же ранее созданный объект сервиса.
Для создания каждого типа сервиса предназначен соответствующий метод: AddTransient(), AddScoped(), AddSingleton().
Как подключить в DI несколько зависимостей одного сервиса?
Таких способов несколько.
Через фабрику
services.AddFactory<IProcessor, string>()
.Add
public class FactoryBuilder<I, P> where I : class { private readonly IServiceCollection _services; private readonly FactoryTypes<I, P> _factoryTypes;
public FactoryBuilder(IServiceCollection services)
{
_services = services;
_factoryTypes = new FactoryTypes<I, P>();
}
public FactoryBuilder<I, P> Add<T>(P p) where T : class, I
{
_factoryTypes.ServiceList.Add(p, typeof(T));
_services.AddSingleton(_factoryTypes);
_services.AddTransient<T>();
return this;
}
}
public class FactoryTypes<I, P> where I : class { public Dictionary<P, Type> ServiceList { get; set; } = new Dictionary<P, Type> (); }
public interface IFactory<I, P> { I Create(P p); } public class Factory<I, P> : IFactory<I, P> where I : class { private readonly IServiceProvider _serviceProvider; private readonly FactoryTypes<I, P> _factoryTypes;
public Factory(IServiceProvider serviceProvider, FactoryTypes<I, P> factoryTypes)
{
_serviceProvider = serviceProvider; _factoryTypes = factoryTypes;
}
public I Create(P p)
{
return (I)_serviceProvider.GetService(_factoryTypes.ServiceList[p]);
}
} //расширение namespace Microsoft.Extensions.DependencyInjection { public static class DependencyExtensions { public static IServiceCollection AddFactory<I, P>(this IServiceCollection services, Action<FactoryBuilder<I, P>> builder) where I : class { services.AddTransient<IFactory<I, P>, Factory<I, P>>(); var factoryBuilder = new FactoryBuilder<I, P>(services); builder(factoryBuilder); return services; } } }
Через IEnumerable
public interface IFactory<I, P>
{
I Create(P p);
}
public class Factory<I, P> : IFactory<I, P> where I : class
{
private readonly IServiceProvider _serviceProvider;
private readonly FactoryTypes<I, P> _factoryTypes;
public Factory(IServiceProvider serviceProvider, FactoryTypes<I,
P> factoryTypes)
{
_serviceProvider = serviceProvider; _factoryTypes =
factoryTypes;
}
public I Create(P p)
{
return
(I)_serviceProvider.GetService(_factoryTypes.ServiceList[p]);
}
}
//расширение
namespace Microsoft.Extensions.DependencyInjection
{
public static class DependencyExtensions
{
public static IServiceCollection AddFactory<I, P>(this
IServiceCollection services, Action<FactoryBuilder<I, P>> builder) where I
: class
{
services.AddTransient<IFactory<I, P>, Factory<I,
P>>();
var factoryBuilder = new FactoryBuilder<I, P>
(services);
builder(factoryBuilder);
return services;
}
}
}
// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped(IService, ServiceA);
services.AddScoped(IService, ServiceB);
services.AddScoped(IService, ServiceC);
}
// Any class that uses the service(s)
public class Consumer
{
private readonly IEnumerable
через типизированный интерфейс public interface IMyInterface where T : class, IMyInterface
Какие сервисы можно внедрять друг в друга без ошибок?
Можно в Transient сервис внедрять как Scoped так и Transient
Изучение механизмов DI. Ответить на вопросы.