patterncsharpMinor
Autowiring publishers/listeners with reflection in Unity Framework
Viewed 0 times
reflectionunitywithlistenerspublishersautowiringframework
Problem
I'm currently building an application with the Microsoft Unity Framework. I also use a simple system of message publishers/listeners inspired from MVVM light and caliburn:
The listener interface
The messenger interface
I started to find it boring to have to inject my messengers to my listeners so they can subscribe, so I thought: "Hey, my Unity container can do that". I've coded a
```
public override void PostBuildUp(IBuilderContext context)
{
base.PostBuildUp(context);
foreach (Type interf in context.Existing.GetType().GetInterfaces().Where(i => i.IsGenericType))
{
//If the interface is of type IMessageListener
if (interf.GetGenericTypeDefinition() == typeof(IMessageListener).GetGenericTypeDefinition())
{
//Get the generic parameter type
Type genericParameter = interf.GetGenericArguments().FirstOrDefault();
//Build the messenger type
Type messengerType = typeof(IMessagePublisher).GetGenericTypeDefinition().MakeGenericType(genericParameter);
//Resolve the messenger
object messenger = _container.Resolve(messengerType);
//Find the subscribe method
MethodInfo subscribeMethod = messenger.GetType().GetMethod("Subscribe");
//Subscribe the listener (the array is ugly, but i just keep getting an error without it)
subscribeMethod.Invoke(messenger, new []{
The listener interface
public interface IMessageListener
{
void Handle(T Message);
}The messenger interface
public interface IMessagePublisher
{
void Subscribe(IMessageListener subscriber);
void Unsubscribe(IMessageListener subscriber);
void Publish(T message);
}I started to find it boring to have to inject my messengers to my listeners so they can subscribe, so I thought: "Hey, my Unity container can do that". I've coded a
UnityExtension which autowires all resolved listener objects with their appropriate messenger(s) by using reflection. Of course, my messengers are ContainerLifeTimeManaged.```
public override void PostBuildUp(IBuilderContext context)
{
base.PostBuildUp(context);
foreach (Type interf in context.Existing.GetType().GetInterfaces().Where(i => i.IsGenericType))
{
//If the interface is of type IMessageListener
if (interf.GetGenericTypeDefinition() == typeof(IMessageListener).GetGenericTypeDefinition())
{
//Get the generic parameter type
Type genericParameter = interf.GetGenericArguments().FirstOrDefault();
//Build the messenger type
Type messengerType = typeof(IMessagePublisher).GetGenericTypeDefinition().MakeGenericType(genericParameter);
//Resolve the messenger
object messenger = _container.Resolve(messengerType);
//Find the subscribe method
MethodInfo subscribeMethod = messenger.GetType().GetMethod("Subscribe");
//Subscribe the listener (the array is ugly, but i just keep getting an error without it)
subscribeMethod.Invoke(messenger, new []{
Solution
typeof(IMessageListener).GetGenericTypeDefinition()You can simplify this to just:
typeof(IMessageListener<>)Why are you combing
Where() with an if? I would stick with one or the other.interf.GetGenericArguments().FirstOrDefault()Don't use
OrDefault when you're not going to deal with the null. That way, when an error happens, you're going to get a descriptive exception right away, instead of a confusing NullReferenceException later.If this is part of the exception handling that you removed, then that makes it hard to review your code properly.
// […] the array is ugly, but i just keep getting an error without itYou have to use an array here,
MethodInfo.Invoke() is not a params method.Code Snippets
typeof(IMessageListener<object>).GetGenericTypeDefinition()typeof(IMessageListener<>)interf.GetGenericArguments().FirstOrDefault()// […] the array is ugly, but i just keep getting an error without itContext
StackExchange Code Review Q#65197, answer score: 3
Revisions (0)
No revisions yet.