Dependency Injection
and
Events
"I want to register to a plain old .NET event of a dependency that is supplied via constructor injection."
Constructor Injection
public interface IDependency { event EventHandler ItHappened; }public class NeedyClass { private readonly IDependency dependency; public NeedyClass(IDependency dependency) { if (dependency == null) throw new ArgumentNullException("dependency"); this.dependency = dependency; this.dependency.ItHappened += this.OnItHappened; } private void OnItHappened(object sender, EventArgs e) { // Handle event here } }
What's wrong with this?
What's wrong?
- Behaviour in the constructor
- Dependency is never called
- No dispose
Third-party Connect
public class NeedyClass { public void DoSomethingInteresting() { // Handle event here } }// Third party: var nc = new NeedyClass(); dependency.ItHappened += (s, e) => nc.DoSomethingInteresting();
-
Much simpler
- NeedyClass doesn't know about dependency
- Dependency doesn't know about NeedyClass
Problems?
Problems
- Subscription
- Remember to subscribe
- Unsubscription
- Hold on to that event
- Remember to unsubscribe
Basically: more fragile
Reactive Extensions
public interface IDependency : IObservable{ } public class NeedyClass : IObserver , IDisposable { private readonly IDisposable subscription; public NeedyClass(IObservable dependency) { if (dependency == null) throw new ArgumentNullException("dependency"); this.subscription = dependency.Subscribe(this); } public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(Unit value) { // Handle event here } public void Dispose() { this.subscription.Dispose(); } }
Pros
- No more IDependency
- Real objects
Cons
- More complicated
- Depends on IObservable, but holds on to IDisposable
- Still doing work in the constructor
Invert all the things!
DI and Events
By soxtoby
DI and Events
- 15