.net framework-如何创建 IServiceProvider 以使用 IServiceProvider 获取已注册的服务实例?
.net framework- how to create IServiceProvider to get already registered service instance using IServiceProvider?
在 .NET Framework 4.6.2 应用程序中,没有内置的 DI 容器,我们使用 LightInject DI 容器来对象初始化,但不知道如何在 Main() 中创建 'IServiceProvider' 对象,以便其他 class 实现可以通过 IServiceProvider
获取已注册的服务实例,而无需使用 new
关键字。
如何创建IServiceProvider
对象?在 .net 框架 4.6.2 应用程序中
public class Program
{
public static void Main()
{
var container = new ServiceContainer();
// calls below extension method
container.RegisterDependencies();
}
}
public static class LightInjectDIExtension
{
/// Registers the application dependencies.
public static void RegisterDependencies(this ServiceContainer container)
{
container.Register<IBackgroundService1, BackgroundService1>();
container.Register<Service2>();
}
}
一旦 IServiceProvider
实例可供使用,我打算执行以下操作
// This is background service app & this class will be
// instantiated once in application lifetime
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceProvider _serviceProvider;
public BackgroundService1(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_serviceProvider.GetService(typeof(Service2));
service2.CallMe();
}
}
根据史蒂文的建议修改
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceContainer_container;
public BackgroundService1 (IServiceContainer container)
//Exception thrown: 'System.InvalidOperationException' in LightInject.dll
{
_container = container;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_container.GetInstance(typeof(Service2));
service2.CallMe();
}
}
一般来说,注入 IServiceProvider
(或任何允许访问未绑定依赖集的抽象是一个坏主意,因为它会导致服务定位器反模式。关于这个反模式的讨论-pattern 可以找到here.
服务定位器仅存在于 Composition Root 之外。但是,您的 BackgroundService1
可能是组合根的一部分,它可能会注入一个 DI 容器 - 或者那里的抽象 - 一个可行的解决方案。请注意,您应该努力将所有业务逻辑排除在组合根之外。这确保 BackgroundService1
纯粹作为代码的机械和平,将操作委托给 classes,运行 实际业务逻辑。
不过,在组合根内部操作时,通常不需要对 DI 容器使用抽象,例如 IServiceProvider
。 Composition Root 已经拥有所有应用程序依赖项的内在知识,包括您的 DI 容器。
这意味着你可以将LightInject的ServiceContainer
直接注入到BackgroundService1
的构造函数中;不需要 IServiceProvider
.
但是,如果您坚持使用 IServiceProvider
抽象,您可以创建一个 IServiceProvider
包装 ServiceContainer
的实现并将其 GetService
方法转发给包装ServiceContainer
。这个包装器 class 可以在 ServiceContainer
.
中注册
在 .NET Framework 4.6.2 应用程序中,没有内置的 DI 容器,我们使用 LightInject DI 容器来对象初始化,但不知道如何在 Main() 中创建 'IServiceProvider' 对象,以便其他 class 实现可以通过 IServiceProvider
获取已注册的服务实例,而无需使用 new
关键字。
如何创建IServiceProvider
对象?在 .net 框架 4.6.2 应用程序中
public class Program
{
public static void Main()
{
var container = new ServiceContainer();
// calls below extension method
container.RegisterDependencies();
}
}
public static class LightInjectDIExtension
{
/// Registers the application dependencies.
public static void RegisterDependencies(this ServiceContainer container)
{
container.Register<IBackgroundService1, BackgroundService1>();
container.Register<Service2>();
}
}
一旦 IServiceProvider
实例可供使用,我打算执行以下操作
// This is background service app & this class will be
// instantiated once in application lifetime
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceProvider _serviceProvider;
public BackgroundService1(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_serviceProvider.GetService(typeof(Service2));
service2.CallMe();
}
}
根据史蒂文的建议修改
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceContainer_container;
public BackgroundService1 (IServiceContainer container)
//Exception thrown: 'System.InvalidOperationException' in LightInject.dll
{
_container = container;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_container.GetInstance(typeof(Service2));
service2.CallMe();
}
}
一般来说,注入 IServiceProvider
(或任何允许访问未绑定依赖集的抽象是一个坏主意,因为它会导致服务定位器反模式。关于这个反模式的讨论-pattern 可以找到here.
服务定位器仅存在于 Composition Root 之外。但是,您的 BackgroundService1
可能是组合根的一部分,它可能会注入一个 DI 容器 - 或者那里的抽象 - 一个可行的解决方案。请注意,您应该努力将所有业务逻辑排除在组合根之外。这确保 BackgroundService1
纯粹作为代码的机械和平,将操作委托给 classes,运行 实际业务逻辑。
不过,在组合根内部操作时,通常不需要对 DI 容器使用抽象,例如 IServiceProvider
。 Composition Root 已经拥有所有应用程序依赖项的内在知识,包括您的 DI 容器。
这意味着你可以将LightInject的ServiceContainer
直接注入到BackgroundService1
的构造函数中;不需要 IServiceProvider
.
但是,如果您坚持使用 IServiceProvider
抽象,您可以创建一个 IServiceProvider
包装 ServiceContainer
的实现并将其 GetService
方法转发给包装ServiceContainer
。这个包装器 class 可以在 ServiceContainer
.