Tom Crosman
Tom Crosman

Reputation: 1285

How can I add an event listener to an object that is instantiated with dependency injection?

Seeing as I don't have a variable to work with when using dependency injection, how would I add an event listener to a service?

Here is the ProjectService

public class ProjectService
{
    protected AppDbContext _db;

    public ProjectService(AppDbContext db)
    {
        _db = db;
    }

    public IQueryable<Project> GetProjects()
    {
        return _db.Projects;
    }

    public Project CreateProject (Project Project)
    {
        Project project = _db.Projects.Add(Project).Entity;
        OnProjectCreated(project);
        _db.SaveChanges();
        return project;
    }

    public Project UpdateProject (Project Project)
    {
        Project project = _db.Projects.Update(Project).Entity;
        _db.SaveChanges();
        return project;
    }

    public Project DeleteProject (Project Project)
    {
        _db.Projects.Remove(Project);
        _db.SaveChanges();
        return Project;
    }

    public event EventHandler<ProjectEventArgs> ProjectCreated;

    protected virtual void OnProjectCreated(Project project)
    {
        ProjectCreated?.Invoke(this, new ProjectEventArgs(project));
    }
}

and this is how I inject it

services.AddTransient<ProjectService>();

Upvotes: 2

Views: 2131

Answers (1)

Nkosi
Nkosi

Reputation: 247088

It is possible to use a factory delegate. Within the delegate the target type can be initialized with its dependencies and then subscribing to the event.

services.AddTransient<ProjectService>(sp => {
    AppDbContext dependency = sp.GetService<AppDbContext>();
    ProjectService target = new ProjectService(dependency);
    target.ProjectCreated += some_event_handler_here;
    return target;
});

But there are many problems that can arise out of this approach.

The handler would end up living in startup.

The DbContext could become a captive dependency depending on its lifetime scope.

Since the nature of the target class is unclear based on its current design, it is uncertain how the target is to be used.

I would however suggest changing the design to use mediator pattern, and pass any notification on to a mediator that can route it to any subscribed handlers. This follows more closely to Single Responsibility Principle and Separation of Concerns.

Upvotes: 3

Related Questions