Нет, и это на самом деле просто дизайн.
Весь смысл DI в том, что сюрпризов в том, как настроена ваша программа: все, что вы настраиваете в ConfigureServices
( в вашем случае, SetupDi
) - это именно то, что вы получаете во время выполнения. Используя атрибуты для настройки DI, можно было бы использовать «нелокальные эффекты», и было бы намного сложнее отследить ошибки, вызванные неправильными или неправильно настроенными зависимостями, вызванными ошибочным атрибутом.
(В этом смысле Я не согласен с дизайном Angular - но это не так c).
(я тоже так чувствую. NET Система DI в Core также несовершенна - слишком много необходимых деталей скрыто за DI Методы расширения инъекций, которые вам необходимо использовать ILSpy или Reflector для однорангового подключения.
В качестве обходного пути вы можете"протестировать" ваши службы DI при запуске приложения, чтобы убедиться, что все настроено с помощью размышляя над каждым IService
в вашем проекте и пытаясь создать экземпляр реализации.
Вот код, который я использую в моих ASP. NET и ASP. NET Базовых проектах для проверки DI Тщательно сконфигурированный:
internal static void TestAllServices( IServiceProvider sp )
{
Assembly[] mySolutionAssemblies = new[]
{
typeof(FromAssemblyX.Foobar).Assemby,
typeof(FromAssemblyY.Foobar).Assemby,
typeof(FromAssemblyZ.Foobar).Assemby,
};
List<Type> allServiceInterfaceTypes = mySolutionAssemblies
.SelectMany( ass => ass.GetTypes() )
.Where( t => t.IsInterface && t.IsPublic )
.Where( /* Filter out interfaces you don't want to verify here */ )
.ToList();
foreach( Type serviceInterfaceType in serviceInterfaceTypes )
{
try
{
Object implementation = sp.GetRequiredService( serviceInterfaceType );
if( implementation is IDisposable disp ) disp.Dispose();
}
catch( Exception ex )
{
// Log an error or throw or set a breakpoint here
}
}
}
Примечания:
- Не передавайте свои "настоящие"
IServiceProvider
в TestAllServices
- вместо этого создайте отдельный экземпляр IServiceProvider
, потому что это Метод будет использовать любую реализацию, которая реализует IDisposable
, даже если они одиночные. - Я рекомендую поместить этот код в
#if DEBUG
, чтобы он не go в производстве. - Существенный недостаток. NET Система DI по умолчанию в Core состоит в том, что невозможно статически отличить реализации "определенных" сервисов от одиночных и переходных сервисов - вы можете обойти это, добавив маркерные интерфейсы в реализации сервисов и обрабатывая их. соответственно.
Еще одно примечание:
Если бы вы действительно хотели, вы можете использовать ту же самую технику allServiceInterfaceTypes
, описанную выше, внутри вашего метода ConfigureServices
перечислять по всему интерфейсу и обнаруживать все типы, реализующие каждый интерфейс, а также обнаруживать любые пользовательские атрибуты этих типов и автоматически регистрировать их в контейнере DI - но я не рекомендую делать это, потому что отражение медленнее, чем при использовании DI по назначению - и конфигурировать такие вещи, как фабричные методы, было бы намного сложнее.