Lui*_*ipe 8 dependency-injection asp.net-core
使用asp.net 5我喜欢我的控制器注入Func<T>而不是T
例如:
public HomeController(Func<Interfaces.IUnitOfWork> uow)
Run Code Online (Sandbox Code Playgroud)
代替
public HomeController(Interfaces.IUnitOfWork uow)
Run Code Online (Sandbox Code Playgroud)
是否可以使用内置DI或我被迫移动到外部DI?
Func<T> 默认情况下没有注册或解决,但没有什么能阻止您自己注册.
例如
services.AddSingleton(provider =>
new Func<IUnitOfWork>(() => provider.GetService<IUnitOfWork>()));
Run Code Online (Sandbox Code Playgroud)
请注意,您还需要以通常的方式注册IUnitOfWork.
您可以Func<T>使用 注册一个或一个代表ServiceCollection。我推荐使用委托,因为它允许您区分具有相同签名的不同方法。
这是一个例子。
public interface IThingINeed {}
public class ThingINeed : IThingINeed { }
public delegate IThingINeed ThingINeedFactory();
public class DelegateRegistrationTests
{
[Test]
public void RegisterDelegateFromDependency()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<IThingINeed, ThingINeed>();
serviceCollection.AddTransient<ThingINeedFactory>(
provider => provider.GetService<IThingINeed>);
var serviceProvider = serviceCollection.BuildServiceProvider();
var factoryMethod = serviceProvider.GetService<ThingINeedFactory>();
var output = factoryMethod();
Assert.IsInstanceOf<ThingINeed>(output);
}
}
Run Code Online (Sandbox Code Playgroud)
这几乎看起来像一个服务定位器,因为我们正在解析的函数实际上是IServiceCollection.GetService<ThingINeedFactory>(). 但这隐藏在组合根中。注入此委托的类取决于委托,而不是实现。
如果要返回的方法属于容器必须解析的类,则可以使用相同的方法。
public interface IThingINeed
{
string SayHello();
}
public class ThingINeed : IThingINeed
{
private readonly string _greeting;
public ThingINeed(string greeting)
{
_greeting = greeting;
}
public string SayHello() => _greeting;
}
public class ThingINeedFactory
{
public IThingINeed Create(string input) => new ThingINeed(input);
}
public delegate IThingINeed ThingINeedFactoryMethod(string input);
public class DelegateRegistrationTests
{
[Test]
public void RegisterDelegateFromDependency()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IThingINeed, ThingINeed>();
serviceCollection.AddSingleton<ThingINeedFactory>();
serviceCollection.AddSingleton<ThingINeedFactoryMethod>(provider =>
provider.GetService<ThingINeedFactory>().Create);
var serviceProvider = serviceCollection.BuildServiceProvider();
var factoryMethod = serviceProvider.GetService<ThingINeedFactoryMethod>();
var created = factoryMethod("abc");
var greeting = created.SayHello();
Assert.AreEqual("abc", greeting);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个扩展方法(也许)使它变得更容易一些:
public static class ServiceCollectionExtensions
{
public static IServiceCollection RegisterDelegate<TSource, TDelegate>(
this IServiceCollection serviceCollection,
Func<TSource, TDelegate> getDelegateFromSource)
where TDelegate : class
{
return serviceCollection.AddSingleton(provider =>
getDelegateFromSource(provider.GetService<TSource>()));
}
}
serviceCollection
.RegisterDelegate<ThingINeedFactory, ThingINeedFactoryMethod>(
factory => factory.Create);
Run Code Online (Sandbox Code Playgroud)
据我所知,使用 ASP.NET Core 中当前默认的 IoC 容器不可能延迟这样的依赖关系。无论如何我都没能让它工作!
要推迟像这样的依赖项的初始化,您需要实现一个现有的、功能更丰富的 IoC 容器。
我写了一个注册服务和工厂的小扩展方法Func<T>( ):
public static class IServiceCollectionExtension
{
public static IServiceCollection AddFactory<TService, TServiceImplementation>(this IServiceCollection serviceCollection)
where TService : class
where TServiceImplementation : class, TService
{
return serviceCollection
.AddTransient<TService, TServiceImplementation>();
.AddSingleton<Func<TService>>(sp => sp.GetRequiredService<TService>);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
serviceCollection
.AddFactory<IMyInterface, MyImplementation>()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2876 次 |
| 最近记录: |