【发布时间】:2020-11-27 06:53:54
【问题描述】:
我正在使用实体框架核心在我的 asp.net 核心应用程序中创建 crud 服务。我的 crud 服务具有事件和处理程序,例如 OnCreated、OnUpdated。
这些事件也应该能够调用其他 crud 服务。
如何做到这一点?
以下是我注入 CRUD 服务的方式:
services.AddTransient<IRoleManager, RoleManager>();
services.AddTransient<IOfficeManager, OfficeManager>();
services.AddTransient<IProjectManager, ProjectManager>();
这是我的 CRUD 服务之一的示例:
public class ProjectManager : IProjectManager
{
protected AppDbContext Db;
public ProjectManager(AppDbContext db)
{
Db = db;
}
public IQueryable<Project> GetProjects()
{
return Db.Projects;
}
public Project CreateProject (Project project)
{
Project Project = Db.Projects.Add(project).Entity;
Db.SaveChanges();
OnProjectCreated(Project);
return Project;
}
public Project UpdateProject (Project project)
{
Project Project = Db.Projects.Update(project).Entity;
Db.SaveChanges();
OnProjectUpdated(Project);
return Project;
}
public Project DeleteProject (Project project)
{
Db.Projects.Remove(project);
Db.SaveChanges();
OnProjectDeleted(project);
return project;
}
public event EventHandler<ProjectManagerEventArgs> ProjectCreated;
public event EventHandler<ProjectManagerEventArgs> ProjectUpdated;
public event EventHandler<ProjectManagerEventArgs> ProjectDeleted;
protected virtual void OnProjectCreated(Project project)
{
ProjectCreated?.Invoke(this, new ProjectManagerEventArgs(project));
}
protected virtual void OnProjectUpdated(Project project)
{
ProjectUpdated?.Invoke(this, new ProjectManagerEventArgs(project));
}
protected virtual void OnProjectDeleted(Project project)
{
ProjectDeleted?.Invoke(this, new ProjectManagerEventArgs(project));
}
}
我可以这样订阅...
services.AddTransient(sp =>
{
AppDbContext dependency = sp.GetService<AppDbContext>();
ProjectManager target = new ProjectManager(dependency);
target.ProjectCreated += new ProjectManagerListener().OnProjectCreated;
return (IProjectManager)target;
});
但这种方式感觉非常草率,并且阻止我的 Handler/Listener 访问其他 CRUD 服务。
如何在 DI 中使用事件?
监听器代码
public class ProjectManagerListener
{
private readonly IClaimManager ClaimManager;
private readonly IRoleManager RoleManager;
public ProjectManagerListener(IClaimManager claimManager, IRoleManager roleManager)
{
ClaimManager = claimManager;
RoleManager = roleManager;
}
public void OnProjectCreated(object source, ProjectManagerEventArgs ProjectEventArgs)
{
foreach (Role role in RoleManager.GetRoles())
{
ClaimManager.CreateClaim(new ProjectRoleClaim() { ProjectId = ProjectEventArgs.Project.Id, RoleId = role.Id });
}
}
}
监听器注入代码
services.AddTransient(sp =>
{
AppDbContext dependency = sp.GetService<AppDbContext>();
IClaimManager ClaimManager = sp.GetService<IClaimManager>();
IRoleManager RoleManager = sp.GetService<IRoleManager>();
ProjectManager target = new ProjectManager(dependency);
target.ProjectCreated += new ProjectManagerListener(ClaimManager, RoleManager).OnProjectCreated;
return (IProjectManager)target;
});
【问题讨论】:
-
您能否详细说明您最终要达到的目标是什么?为什么需要在服务
IProjectManager的DI注册内创建ProjectManagerListener的实例? -
也许我想在创建项目时发送电子邮件。当我的任何 crud 项目被创建、更新、删除等时,我希望发生的任何事件。
-
您已经有一个事件,只需在使用
IProjectManager的服务的构造函数中订阅它。还是我错过了什么? -
如图所示,我可以在 startup.cs 中以非常草率的方式订阅事件。但我可能需要访问其他 crud 服务。假设我正在构建一封电子邮件,并且需要从其他与传递对象相关的 CRUD 服务中收集更多信息。
-
嗯,没用 提供的信息不多……你用了多线程吗?
标签: c# asp.net-core dependency-injection entity-framework-core