2011-05-23 9 views
5

Estoy teniendo un momento difícil para implementar eventing en un proyecto reciente.structuremap ObjectFactory.GetAllInstances <IHandle <TEvent>>()

He comprobado que StructureMap está escaneando el ensamble apropiado y añadiendo manejadores de sucesos

Scan(cfg => 
      { 
       cfg.TheCallingAssembly(); 
       cfg.IncludeNamespace("ABC.EventHandler"); 
       cfg.ConnectImplementationsToTypesClosing(typeof(IHandle<>)); 

      }); 

public class StructureMapEventDispatcher : IEventDispatcher 
    { 

     public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent 
     { 

      foreach (var handler in ObjectFactory.GetAllInstances<IHandle<TEvent>>()) 
      { 

       handler.Handle(eventToDispatch); 

      } 

     } 

    } 

Antes solía disparar eventos de dominio. Algo así como Dispatcher.RaiseEvent(new [domainEvent class](x,y,z));

y el evento se encenderá. Tenía que cambiar el diseño en el que estoy ahora collectiong eventos en una colección

_domainEvents = new Collection<IDomainEvent>(); 

y luego levantándolo después de haber salvado el dominio al repositorio

public static void Raise(ICollection<IDomainEvent> domainEvents) 
     { 
      foreach (var domainEvent in domainEvents) 
      { 
       DomainEventDispatcher.Raise(domainEvent); 
      } 

     } 

pero ahora

ObjectFactory.GetAllInstances<IHandle<TEvent>>() devuelve 0 recuento de controladores

si miro para

ObjectFactory.GetAllInstances<IHandle<DomainEventClass>>() vuelve colección de controladores correctamente (actualmente tengo 2 y se nota 2 recuento)

... Estoy asumiendo que esto tiene algo que ver con eventos que están siendo criados como de tipo IDomainEvent en lugar de tipo real y que está haciendo es difícil para structuremap resolverlo.

¿Cómo puedo resolver este problema?

Saludos,

El mar

-

Edición 1:

he conformado ese contenedor struturemap contiene todos los controladores de eventos escaneadas de la asamblea.

Editar 2

No sé cómo hacer esta pregunta a atraer más atención. Estoy agregando recompensas por una solución para lograr los resultados deseados. Si la pregunta no está clara, por favor pregunte.

Básicamente quiero que el ObjectFactory.GetAllInstances<IHandle<TEvent>>() para volver manejadores para TEvent donde TEvent es de tipo IDomainEvent. Los eventos que se deben generar se almacenan en Collection of IDomainEvent y se generan después del hecho de que Domain se guardó (de la capa de servicio).

Pienso que debería haber alguna manera de hacer StructureMap saben que el caso planteado como IDomainEvent es en realidad de Tipo DomainEvent

var = eventsToRaise distribuidor.EventsToRaise(); Adición de la información de la ventana de depuración:

Después de los acontecimientos se han planteado en la ventana despachador

enter image description here

Editar 3: Eventhough eventToRaise muestra como "DealerName cambiado" y "DealerCommunicationChanged"
typeof (TEvent) da como Tipo Domain.IDomainEvent

I Guesss si es posible conseguir podrán emitir t o Tipo de la derecha (desde dondequiera VS ventana de vigilancia está recibiendo información) que el problema podría resolverá

Resultado ----- ---

Tanto enfoque funcionó. Acerqué ambos a otros 2 miembros de mi equipo y pensamos que la solución sin reflexión debía seleccionarse como la respuesta correcta.

Hoy vamos a estar haciendo una prueba con cambio de aplicación y ver si hay algún problema con esta solución en la solución.

He upvoted solución basada en la reflexión como lo es también la respuesta correcta.


+0

@Still esperando por cualquier sugerencia. – TheMar

+0

¿El 'ObjectFactory.GetAllInstances >()' devolverá la lista que estás buscando? – arootbeer

+0

No, devuelve la lista sin controladores. – TheMar

Respuesta

1

en lugar de un enfoque basado en la reflexión, yo recomendaría el uso de un registro de aferrarse a la información de tipo para usted. Algo como esto:

interface IEventRecord 
{ 
    void Dispatch(IEventDispatcher dispatcher); 
} 

public class EventRecord<TEvent> : IEventRecord where TEvent : IDomainEvent 
{ 
    TEvent theEvent; 

    public EventRecord(TEvent theEvent) 
    { 
     this.theEvent = theEvent; 
    } 

    public void Dispatch(IEventDispatcher dispatcher) 
    { 
     dispatcher.Dispatch(theEvent); 
    } 
} 

Si encuentra una instancia de un registros de eventos a ser engorroso, un ayudante podría inferir el parámetro de tipo de esta manera:

public static EventRecord<TEvent> CreateEventRecord<TEvent>(TEvent theEvent) where TEvent : IDomainEvent 
{ 
    return new EventRecord<TEvent>(theEvent); 
} 

que le permitiría a una instancia registros de eventos como este:

var record = CreateEventRecord(myDomainEvent); 

Entonces, en lugar de mantenerse en una colección de IDomainEvent s, los sujeta una colección de IEventRecords que sujetan el tipo de datos necesarios para elevarse:

foreach (var eventRecord in Records) 
{ 
    eventRecord.Dispatch(myDispatcher); 
} 
+0

Gracias por el código y la explicación. Intentaré implementarlo y actualizarlo – TheMar

+0

un poco confuso "eventRecord.Raise (myDispatcher);" ¿debería ser eventRecord.Dispatch (myDispatcher)? – TheMar

+0

@TheMar - ¡sí, debería! Actualizado. –

4

Como usted dice, el problema es que usted está pidiendo esquema de la estructura de todas las instancias de IHandle<IDomainEvent> y tiene ningunos de los cuales, StructureMap tiene manejadores de eventos concretos. Que había necesidad de construir el tipo que utiliza el tipo real del evento y luego pedir todos los manipuladores de este caso:

 Type genericHandler = typeof(IHandle<>); 
     Type[] typeArgs = { eventToDispatch.GetType() }; 
     Type neededHandler = genericHandler.MakeGenericType(typeArgs); 
     var handlers = ObjectFactory.GetAllInstances(neededHandler); 

el problema es que usted termina con un IList de objetos y hay que echarlos al tipo de controlador correcto y obtener un poco complicado .... una posible solución es utilizar la reflexión para llamar al método Handle():

 var methodInfo = neededHandler.GetMethod("Handle"); 
     object[] methodArgs = new object[] { eventToDispatch }; 
     foreach (var h in handlers) 
     { 
      methodInfo.Invoke(h, methodArgs); 
     } 
+0

Intentaré aplicar esto tan pronto como regrese del almuerzo y actualizo los resultados. – TheMar

Cuestiones relacionadas