Unity - Part 7: Adding Interfaces
Updated: thanks, Thomas Levesque (@thomaslevesque)!
Another post on the Unity series, this time, adding interfaces to proxies. Previous posts here (Registration by Convention), here (Injecting Values), here (Extensions), here (Aspect-Oriented Programming), here (Dependency Injection) and here (Introduction).
Unity can be used to inject additional interfaces to proxies generated for some type. We can easily add these interfaces at registration time but then we need to implement a behavior that can intercept calls to these interfaces and act accordingly.
A typical example is implementing INotifyPropertyChanged. Let’s see how we can register a type with this additional interface, first, by XML:
1: <register type="MyNamespace.IMyInterface" mapTo="MyNamespace.MyClass">
2: <addInterface type="System.ComponnetModel.INotifyPropertyChanged"/>
3: </register>
And by code:
1: unity.RegisterType<IMyInterface, MyClass>(new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<NotifyPropertyChangedInterceptionBehavior>(), new AdditionalInterface<INotifyPropertyChanged>() });
Do note that I am explicitly setting the interceptor as InterfaceInterceptor, other ways exist, see part 3 of this series.
Now, let’s see the NotifyPropertyChangedBehavior class:
1: public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
2: {
3: var result = getNext()(input, getNext);
4:
5: if (input.MethodBase.IsSpecialName == true)
6: {
7: if (input.MethodBase.Name == "add_PropertyChanged")
8: {
9: this.handlers += (input.Arguments[0] as PropertyChangedEventHandler);
10:
11: result = input.CreateMethodReturn(null, input.Arguments);
12: }
13: else if (input.MethodBase.Name == "remove_PropertyChanged")
14: {
15: this.handlers -= (input.Arguments[0] as PropertyChangedEventHandler);
16:
17: result = input.CreateMethodReturn(null, input.Arguments);
18: }
19: else if (input.MethodBase.Name.StartsWith("set_") == true)
20: {
21: this.handlers(input.Target, new PropertyChangedEventArgs(input.MethodBase.Name.Substring(4)));
22: }
23: }
24:
25: return (result);
26: }
Finally, sample usage:
1: var component = unity.Resolve<IMyInterface>();
2: var npc = component as INotifyPropertyChanged;
3:
4: npc.PropertyChanged += delegate(Object source, PropertyChangedEventArgs args)
5: {
6: //raised with args.PropertyName = MyProperty
7: };
8:
9: component.MyProperty = "Some Value"; //raises PropertyChanged event
Still lots of things to talk about Unity, stay tuned for more!