Поддерживает ли инжекционная поддержка зависимостей .net Lazy <T>
Я пытаюсь использовать общий класс Lazy для создания дорогостоящего класса с расширением расширения .net core. Я зарегистрировал тип IRepo, но я не уверен, что будет выглядеть регистрация класса Lazy или если он даже поддерживается. В качестве обходного пути я использовал этот метод http://mark-dot-net.blogspot.com/2009/08/lazy-loading-of-dependencies-in-unity.html
config:
public void ConfigureService(IServiceCollection services)
{
services.AddTransient<IRepo, Repo>();
//register lazy
}
контроллер:
public class ValuesController : Controller
{
private Lazy<IRepo> _repo;
public ValuesController (Lazy<IRepo> repo)
{
_repo = repo;
}
[HttpGet()]
public IActionResult Get()
{
//Do something cheap
if(something)
return Ok(something);
else
return Ok(repo.Value.Get());
}
}
Ответы
Ответ 1
Здесь другой подход, который поддерживает общую регистрацию Lazy<T>
, так что любой тип может быть разрешен лениво.
services.AddTransient(typeof(Lazy<>), typeof(Lazier<>));
internal class Lazier<T> : Lazy<T> where T : class
{
public Lazier(IServiceProvider provider)
: base(() => provider.GetRequiredService<T>())
{
}
}
Ответ 2
Вам нужно только добавить регистрацию для фабричного метода, который создает объект Lazy<IRepo>
.
public void ConfigureService(IServiceCollection services)
{
services.AddTransient<IRepo, Repo>();
services.AddTransient<Lazy<IRepo>>(provider => new Lazy<IRepo>(provider.GetService<IRepo>));
}
Ответ 3
Я использую технику Lazier выше в некоторых частях моего кода сегодня, но я обнаружил, что должен был удалить его, когда я хотел использовать
IEnumerable<Lazy<ISomething>>
Постановка на учет:
services.AddLazier();
services.AddTransient<ISomething, SomeThing1>();
services.AddTransient<ISomething, SomeThing2>();
Раствор для инъекций:
public class IndexModel : PageModel
{
private IEnumerable<ISomething> _someThings;
private IEnumerable<Lazy<ISomething>> _someLazyThings;
public IndexModel(IEnumerable<ISomething> someThings,
IEnumerable<Lazy<ISomething>> someLazyThings)
{
_someThings = someThings;
_someLazyThings = someLazyThings;
}
public void OnGet()
{
List<string> names = new List<string>();
var countSomeThings = _someThings.Count(); // 2 as expected
var countSomeLazyThings = _someLazyThings.Count(); // 1. huh?
foreach (var lazyObject in _someLazyThings)
{
names.Add(lazyObject.Value.Name);
}
}
}
Я не копался в источнике, чтобы точно выяснить, почему я не получаю 2 в моем
IEnumerable<Lazy<ISomething>>
против
//services.AddLazier();//REMOVED
services.AddTransient<ISomething, SomeThing1>();
services.AddTransient<ISomething, SomeThing2>();
services.AddLazyTransient<ISomething, SomeThing1>();
services.AddLazyTransient<ISomething, SomeThing2>();
Результат (работает как я хочу)..
public class IndexModel : PageModel
{
private IEnumerable<ISomething> _someThings;
private IEnumerable<Lazy<ISomething>> _someLazyThings;
public IndexModel(IEnumerable<ISomething> someThings,
IEnumerable<Lazy<ISomething>> someLazyThings)
{
_someThings = someThings;
_someLazyThings = someLazyThings;
}
public void OnGet()
{
List<string> names = new List<string>();
var countSomeThings = _someThings.Count(); // 2 as expected
var countSomeLazyThings = _someLazyThings.Count(); // 2 as expected
foreach (var someLazyThing in _someLazyThings)
{
names.Add(someLazyThing.Value.Name);
}
}
}
нижеприведенные расширения IServiceCollection показывают, как я регистрирую сервисы.
foreach (var exchange in exchanges)
{
services.AddTransient<Lazy<ITokenExchangeHandler>>(serviceProvider =>
{
return new Lazy<ITokenExchangeHandler>(() =>
{
var tokenExchangeHandler = serviceProvider.GetRequiredService<PipelineTokenExchangeHandler>();
tokenExchangeHandler.Configure(exchange);
return tokenExchangeHandler;
});
});
}
public static class AspNetCoreServiceCollectionExtensions
{
public static IServiceCollection AddLazyTransient<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
services.AddTransient<TImplementation>();
services.AddTransient<Lazy<TService>>(serviceProvider =>
{
return new Lazy<TService>(() =>
{
var impl = serviceProvider.GetRequiredService<TImplementation>();
return impl;
});
});
return services;
}
}