[C#] Blazor练习 依赖注入
[C#] Blazor练习 依赖注入2
如何注册服务?
在 Blazor 中,需要先注册服务,然后才能将其注入组件。有几种方法可以注册服务,例如按其类或接口名称注册。通常,服务在 Program.cs 文件中注册,该文件是配置应用程序的依赖项注入容器的位置。
要注册服务,您需要在 Program.cs 文件中的 和 方法之间插入注册码。这可确保服务在需要时可用于应用程序的依赖项注入容器。WebApplication.CreateBuilder(args)builder.Build()
按类注册服务
若要使用类名在 Blazor 中注册服务,可以按照以下步骤操作:
- 定义要注册为服务的类。例如,您可能有一个具有以下定义的类:
MyService
public class MyService
{
public string ExampleString { get; set; } = "";
}
- 在 Program.cs 文件中,通过在 和 调用之间添加以下代码行来配置应用程序的依赖项注入容器:
WebApplication.CreateBuilder(args)builder.Build()
builder.Services.AddTransient<MyService>();
此MyService代码注册为临时服务。还有其他类型的服务,例如作用域和单一实例,稍后将在本教程中介绍。
按接口注册服务
若要使用其接口名称在 Blazor 中注册服务,可以按照以下步骤操作:
- 定义要注册为服务的接口。例如,假设您有一个具有以下定义的接口:
IService
public interface IService
{
}
- 创建实现接口的类。例如,您可以创建一个类:
IServiceServiceWithInterface
public class ServiceWithInterface : IServiceInterface
{
}
- 通过添加以下代码行在 Program.cs 文件中配置 :
ServiceProvider
builder.Services.AddTransient<IServiceInterface, ServiceWithInterface>();
使用参数注册服务
有时,通用服务ServiceWithParameter需要输入参数才能正常运行。例如,数据访问层服务可能需要数据库的连接字符串。考虑以下几点:
public class ServiceWithParameter
{
public string ExampleString { get; set; } = "";
public ServiceWithParameter(string exampleString)
{
ExampleString = exampleString;
}
}
如果在构造时不提供参数,则不会创建该参数。若要指导如何使用必要的参数构造 ,可以使用以下代码:exampleStringServiceWithParameterServiceProviderServiceWithParameter
builder.Services.AddTransient<ServiceWithParameter>(serviceProvider => new("Blazor School"));
注册依赖服务
一个服务可以依赖于另一个服务。例如,如果 Web 应用程序依赖于数据库服务来存储和检索数据,则该 Web 应用程序将被视为依赖服务,而数据库服务将被视为父服务或上游服务。请考虑以下服务:
public class DependentService
{
public ServiceWithParameter UpstreamService { get; set; }
public DependentService(ServiceWithParameter upstreamService)
{
UpstreamService = upstreamService;
}
}
然后,上游服务会自动注入到依赖服务。您只需要按如下方式注册:
builder.Services.AddTransient<DependentService>();
使用参数注册依赖服务
当一个服务依赖于另一个服务并且需要输入参数时,您需要提供有关如何创建服务的说明。对于需要输入参数的依赖服务,请考虑以下代码:ServiceProvider
public class DependentServiceWithParameter
{
public string ExampleString { get; set; } = "";
public ServiceWithParameter UpstreamService { get; set; }
public DependentServiceWithParameter(string exampleString, ServiceWithParameter upstreamService)
{
ExampleString = exampleString;
UpstreamService = upstreamService;
}
}
若要使用依赖服务及其上游服务和输入参数注册依赖服务,可以使用以下代码:
builder.Services.AddTransient<DependentServiceWithParameter>(serviceProvider=> new("Blazor School", serviceProvider.GetRequiredService<ServiceWithParameter>()));
服务范围之间的比较
注册服务时,必须指定其范围。每个作用域都有自己的生存期,可以从三个不同的作用域中进行选择:
- 单例 Singleton
- 作用域范围 Scoped
- 瞬态 Transient
单例服务范围
单一实例作用域用于注册应仅创建一次并在整个应用程序之间共享的服务。这意味着该服务的同一实例将用于需要它的所有用户,这对于性能优化和减少内存使用非常有用。下图说明了单一实例服务范围:
作用域内服务范围
作用域服务作用域用于注册应为每个浏览器选项卡创建一次的服务。下图说明了作用域内的服务作用域:
瞬态服务范围
对于瞬态服务,每次注入实例时都会创建一个新实例。下图说明了暂时性服务范围:ServiceProvider
自动注册服务
注册服务时,需要指定服务的范围。如果您的网站有许多服务,您可以通过以下步骤自动注册服务来简化流程:
- 为作用域服务、单一实例服务和瞬态服务创建接口。
public interface IScopedService
{
}
public interface ISingletonService
{
}
public interface ITransientService
{
}
- 使用反射扫描并注册程序.cs文件中的服务:
...
ScanAndRegisterServices(builder.Services);
...
static void ScanAndRegisterServices(IServiceCollection services)
{
var currentAssembly = Assembly.GetExecutingAssembly();
var allTypes = currentAssembly.GetTypes().Concat(
currentAssembly
.GetReferencedAssemblies()
.SelectMany(assemblyName => Assembly.Load(assemblyName).GetTypes()))
.Where(type => !type.IsInterface && !type.IsAbstract);
var scopedServices = allTypes.Where(type => typeof(IScopedService).IsAssignableFrom(type));
foreach (var type in scopedServices)
{
services.AddScoped(type);
}
var transientServices = allTypes.Where(type => typeof(ITransientService).IsAssignableFrom(type));
foreach (var type in transientServices)
{
services.AddTransient(type);
}
var singletonServices = allTypes.Where(type => typeof(ISingletonService).IsAssignableFrom(type));
foreach (var type in singletonServices)
{
services.AddTransient(type);
}
}
- 实现其中一个接口来创建服务:
public class AutoTransientService : ITransientService
{
public Guid ExampleId { get; set; } = Guid.NewGuid();
}
这样,将根据服务的范围自动注册服务,而无需为每个服务显式注册。ServiceProvider
构造函数注入
构造函数注入是面向对象编程中使用的一种技术,其中注册的服务被注入到依赖服务的构造函数中。在此方法中,依赖服务通过其构造函数参数声明对上游服务的依赖关系。
public class DependentService
{
public ServiceWithParameter UpstreamService { get; set; }
public DependentService(ServiceWithParameter upstreamService)
{
UpstreamService = upstreamService;
}
}
在上面的代码中,的构造函数将 的实例作为参数。这允许依赖服务访问和使用上游服务提供的功能。DependentServiceServiceWithParameter
属性注入
在 Blazor 中,属性注入是一种技术,用于通过将组件(如服务或数据源)分配给组件的属性来为组件提供依赖项。这可以通过在组件中使用属性或指令来实现。[Inject]@inject
例如,在组件中使用指令,如下所示:@inject
@inject MyService MyService
或者,可以将属性用于组件中的属性,如下所示:[Inject]
[Inject]
public MyService MyService { get; set; }