将组件的依赖注入方法移动到 Blazor 服务器端中的单独 CS 库
Move component's Dependency Injected methods to separate CS library in Blazor Server-Side
想要在单独的库中的单独的 .cs 文件 and/or 中制作可重复使用的 functions/methods。我当然知道该怎么做,我的问题是在我需要使用依赖注入元素的情况下我不知道该怎么做。
例如,这是一个非常简单的函数,用于获取用户的 属性:
[Inject]
public UserManager<IdentityUser> UserManager { get; set; }
public async Task<string> GetUserId(string emailName)
{
var user = await userManager.FindByNameAsync(emailName);
if (user == null)
return null;
return user.Id;
}
这在每个剃须刀中都有效 file/component,如果(!)组件已初始化。如果不是,则注入的服务也未初始化并出现空异常错误。
我不想 rewrite/copy 这个代码片段到我想使用的每个组件中,所以我想为它创建一个 class 或库。正确的方法应该是什么?最好的事情是,如果我可以将这些功能移动到单独的 Class 库或 Razor Class 库中。
更新:
@Nkosi 提供了完美的解决方案,但我想考虑一下。
之前的代码示例非常小,那么如果我的自定义方法需要 2-3-4 或更多 DI 怎么办?例如(在 Razor 组件中):
[Inject]
public UserManager<IdentityUser> UserManager { get; set; }
[Inject]
public SignInManager<IdentityUser> SignInManager { get; init; }
[Inject]
public IJSRuntime jsRuntime { get; init; }
[Inject]
public CookieAuthenticationOptions cookieAuthenticationOptions { get; set; }
[Inject]
public IOptionsMonitor<CookieAuthenticationOptions> c_options { get; set; }
public async Task<string> GetUserWithOtherStuff(string email, string psw)
{
cookieAuthenticationOptions = c_options.Get("schema");
var user = await UserManager.FindByNameAsync(email);
var valid = await SignInManager.UserManager.CheckPasswordAsync(user, psw);
// etc..
return something;
}
将其移至单独的 class / 图书馆
public interface IUserService {
Task<string> GetUserId(string emailName);
}
public class UserService : IUserService {
private readonly UserManager<IdentityUser> userManager;
public UserService(UserManager<IdentityUser> userManager) {
this.userManager = userManager;
}
public async Task<string> GetUserId(string emailName) {
var user = await userManager.FindByNameAsync(emailName);
if (user == null)
return null;
return user.Id;
}
}
并在需要的地方注入封装服务
[Inject]
public IUserService UserService { get; set; }
确保所有必要的依赖项都已注册到服务集合。
可以做一个扩展方法来对需要的依赖注册进行分组
public static IServiceCollection AddUserServices(this IServiceCollection services) {
services
.AddScoped<IUserService, UserService>()
.AddIdentity<.....>()
//... add what is needed for this library library to function
return services;
}
和invoked/reused需要的地方
//...
services.AddUserServices();
//...
小心像 UserManager 这样的常见注入。
如果它们被注入到多个其他服务中,而这些服务又被注入到同一个页面上,您最终可能会因线程异常而炸毁您的页面。
例如,在市场页面中,您可能有一项服务可以查找当前用户的现有资金,另一项服务可以检查用户添加的项目,以及其他一些都依赖于了解当前用户 ID。
如果您只是愉快地将访问 UserManager 的自定义服务注入到大量嵌套组件中,您可能会像我第一次学习 Blazor 时那样悲痛欲绝。
想要在单独的库中的单独的 .cs 文件 and/or 中制作可重复使用的 functions/methods。我当然知道该怎么做,我的问题是在我需要使用依赖注入元素的情况下我不知道该怎么做。 例如,这是一个非常简单的函数,用于获取用户的 属性:
[Inject]
public UserManager<IdentityUser> UserManager { get; set; }
public async Task<string> GetUserId(string emailName)
{
var user = await userManager.FindByNameAsync(emailName);
if (user == null)
return null;
return user.Id;
}
这在每个剃须刀中都有效 file/component,如果(!)组件已初始化。如果不是,则注入的服务也未初始化并出现空异常错误。
我不想 rewrite/copy 这个代码片段到我想使用的每个组件中,所以我想为它创建一个 class 或库。正确的方法应该是什么?最好的事情是,如果我可以将这些功能移动到单独的 Class 库或 Razor Class 库中。
更新:
@Nkosi 提供了完美的解决方案,但我想考虑一下。 之前的代码示例非常小,那么如果我的自定义方法需要 2-3-4 或更多 DI 怎么办?例如(在 Razor 组件中):
[Inject]
public UserManager<IdentityUser> UserManager { get; set; }
[Inject]
public SignInManager<IdentityUser> SignInManager { get; init; }
[Inject]
public IJSRuntime jsRuntime { get; init; }
[Inject]
public CookieAuthenticationOptions cookieAuthenticationOptions { get; set; }
[Inject]
public IOptionsMonitor<CookieAuthenticationOptions> c_options { get; set; }
public async Task<string> GetUserWithOtherStuff(string email, string psw)
{
cookieAuthenticationOptions = c_options.Get("schema");
var user = await UserManager.FindByNameAsync(email);
var valid = await SignInManager.UserManager.CheckPasswordAsync(user, psw);
// etc..
return something;
}
将其移至单独的 class / 图书馆
public interface IUserService {
Task<string> GetUserId(string emailName);
}
public class UserService : IUserService {
private readonly UserManager<IdentityUser> userManager;
public UserService(UserManager<IdentityUser> userManager) {
this.userManager = userManager;
}
public async Task<string> GetUserId(string emailName) {
var user = await userManager.FindByNameAsync(emailName);
if (user == null)
return null;
return user.Id;
}
}
并在需要的地方注入封装服务
[Inject]
public IUserService UserService { get; set; }
确保所有必要的依赖项都已注册到服务集合。
可以做一个扩展方法来对需要的依赖注册进行分组
public static IServiceCollection AddUserServices(this IServiceCollection services) {
services
.AddScoped<IUserService, UserService>()
.AddIdentity<.....>()
//... add what is needed for this library library to function
return services;
}
和invoked/reused需要的地方
//...
services.AddUserServices();
//...
小心像 UserManager 这样的常见注入。
如果它们被注入到多个其他服务中,而这些服务又被注入到同一个页面上,您最终可能会因线程异常而炸毁您的页面。
例如,在市场页面中,您可能有一项服务可以查找当前用户的现有资金,另一项服务可以检查用户添加的项目,以及其他一些都依赖于了解当前用户 ID。
如果您只是愉快地将访问 UserManager 的自定义服务注入到大量嵌套组件中,您可能会像我第一次学习 Blazor 时那样悲痛欲绝。