/// <summary> /// Add the ability to resolve an instance of <typeparam name="T"></typeparam> /// Without adding a resolver the bus will attempt to find and call the default /// constructor to create an instance when adding handlers from assemblies. /// Use <see cref="AddResolver{T}"/> if your handler does not have default constructor /// or you want to re-use an instance. /// </summary> /// <example> /// <code> /// // For type MessageHandler, call the c'tor that takes an IBus parameter /// bus.AddResolver(()=> new MessageHandler(bus)); /// // find all the handlers in assemblies named *handlers.dll" in the current directory in the namespace /// "MyCorp.MessageHandlers /// bus.AddHandlersAndTranslators(Directory.GetCurrentDirectory(), "*handlers.dll", "MyCorp.MessageHandlers"); /// </code> /// </example> /// <typeparam name="T">The type of instance to resolve. Typically of type IConsumer{TMessage}</typeparam> /// <param name="bus">The <seealso cref="IBus"/> instance this will apply to</param> /// <param name="resolver">A delegate that returns an instance of <typeparamref name="T"/></param> public static void AddResolver <T>(this Patterns.Bus bus, Func <T> resolver) { if (!busResolverDictionaries.ContainsKey(bus)) { busResolverDictionaries.Add(bus, new Dictionary <Type, Delegate>()); } var dictionary = busResolverDictionaries[bus]; dictionary[typeof(T)] = resolver; }
public static void SetServiceLocator(this Patterns.Bus bus, IServiceLocator serviceLocator) { if (bus == null) { throw new ArgumentNullException(nameof(bus)); } if (serviceLocator == null) { throw new ArgumentNullException(nameof(serviceLocator)); } if (!busServiceLocators.ContainsKey(bus)) { busServiceLocators.Add(bus, serviceLocator); } else { busServiceLocators[bus] = serviceLocator; } }
/// <summary> /// Dynamically load message handlers by filename in a specific directory. /// </summary> /// <example> /// <code> /// // find all the handlers in assemblies named *handlers.dll" in the current directory in the namespace /// "MyCorp.MessageHandlers /// bus.AddHandlersAndTranslators(Directory.GetCurrentDirectory(), "*handlers.dll", "MyCorp.MessageHandlers"); /// </code> /// </example> /// <param name="bus">The <seealso cref="IBus"/> instance this will apply to</param> /// <param name="directory">What directory to search</param> /// <param name="wildcard">What filenames to search</param> /// <param name="namespace">Include IConsumers{TMessage} within this namespace</param> public static void AddHandlersAndTranslators(this Patterns.Bus bus, string directory, string wildcard, string @namespace) { if (!busResolverDictionaries.ContainsKey(bus)) { busResolverDictionaries.Add(bus, new Dictionary <Type, Delegate>()); } IServiceLocator serviceLocator = busServiceLocators.ContainsKey(bus) ? busServiceLocators[bus] : new ActivatorServiceLocator(); IEnumerable <Type> consumerTypes = typeof(IConsumer <>).ByImplementedInterfaceInDirectory(directory, wildcard, @namespace); foreach (var consumerType in consumerTypes) { var pipeImplementationInterface = consumerType.GetInterfaces() .FirstOrDefault(t => !t.IsGenericTypeDefinition && t.GetGenericTypeDefinition() == typeof(IPipe <,>)); if (pipeImplementationInterface != null) { var translatorType = consumerType; var messageTypes = pipeImplementationInterface.GetGenericTypeArguments(); // get instance of pipe var translatorInstance = busResolverDictionaries[bus].ContainsKey(translatorType) ? InvokeFunc(busResolverDictionaries[bus][translatorType]) : serviceLocator.GetInstance(translatorType); // get instance of the helper that will help add specific handler // code to the bus. var helperType1 = typeof(PipeAttachConsumerHelper <,>).MakeGenericType(messageTypes); var helperType1Instance = Activator.CreateInstance(helperType1); var attachConsumerMethodInfo = helperType1.GetMethod("AttachConsumer"); attachConsumerMethodInfo.Invoke(helperType1Instance, new[] { translatorInstance, bus }); var inType = messageTypes[0]; var helperType = typeof(BusAddhHandlerHelper <>).MakeGenericType(inType); var helperInstance = Activator.CreateInstance(helperType); var addHandlerMethodInfo = helperType.GetMethod("AddHandler"); addHandlerMethodInfo.Invoke(helperInstance, new[] { bus, translatorInstance }); } else { var consumerImplementationInterface = consumerType.GetInterfaces() .FirstOrDefault(t => !t.IsGenericTypeDefinition && t.GetGenericTypeDefinition() == typeof(IConsumer <>)); Debug.Assert(consumerImplementationInterface != null, "Unexpected state enumerating implementations of IConsumer<T>"); var messageTypes = consumerImplementationInterface.GetGenericTypeArguments(); var helperType = typeof(BusAddhHandlerHelper <>).MakeGenericType(messageTypes); var helperInstance = Activator.CreateInstance(helperType); var addHandlerMethodInfo = helperType.GetMethod("AddHandler"); var handlerInstance = busResolverDictionaries[bus].ContainsKey(consumerType) ? InvokeFunc(busResolverDictionaries[bus][consumerType]) : serviceLocator.GetInstance(consumerType); addHandlerMethodInfo.Invoke(helperInstance, new[] { bus, handlerInstance }); } } }