/// <summary> /// Enforce messaging rules. Make sure, the message can be used within the <see cref="IBus.Send(object[])"/>. /// </summary> /// <param name="messageType">Event, Command or message</param> /// <param name="messageIntent">The intent of the message</param> public static void AssertIsValidForSend(Type messageType, MessageIntentEnum messageIntent) { if (MessageConventionExtensions.IsEventType(messageType) && messageIntent != MessageIntentEnum.Publish) { throw new InvalidOperationException("Events can have multiple recipient so they should be published"); } }
void RegisterMessageOwnersAndBusAddress(IEnumerable <Type> knownMessages) { var unicastConfig = GetConfigSection <UnicastBusConfig>(); var router = new StaticMessageRouter(knownMessages); Configurer.RegisterSingleton <IRouteMessages>(router); if (unicastConfig == null) { return; } if (!string.IsNullOrWhiteSpace(unicastConfig.ForwardReceivedMessagesTo)) { var forwardAddress = Address.Parse(unicastConfig.ForwardReceivedMessagesTo); busConfig.ConfigureProperty(b => b.ForwardReceivedMessagesTo, forwardAddress); } busConfig.ConfigureProperty(b => b.TimeToBeReceivedOnForwardedMessages, unicastConfig.TimeToBeReceivedOnForwardedMessages); var messageEndpointMappings = unicastConfig.MessageEndpointMappings.Cast <MessageEndpointMapping>() .OrderByDescending(m => m) .ToList(); foreach (var mapping in messageEndpointMappings) { mapping.Configure((messageType, address) => { if (!MessageConventionExtensions.IsMessageType(messageType)) { return; } router.RegisterRoute(messageType, address); }); } }
/// <summary> /// Lists all message type for which we have handlers /// </summary> public IEnumerable <Type> GetMessageTypes() { return(from handlers in handlerList.Values from typeHandled in handlers where MessageConventionExtensions.IsMessageType(typeHandled) select typeHandled); }
static bool IsEncryptedMember(MemberInfo arg) { var propertyInfo = arg as PropertyInfo; if (propertyInfo != null) { if (propertyInfo.GetIndexParameters().Length > 0) { if (MessageConventionExtensions.IsEncryptedProperty(propertyInfo)) { throw new Exception("Cannot encrypt or decrypt indexed properties that return a WireEncryptedString."); } return(false); } return(MessageConventionExtensions.IsEncryptedProperty(propertyInfo)); } var fieldInfo = arg as FieldInfo; if (fieldInfo != null) { return(fieldInfo.FieldType == typeof(WireEncryptedString)); } return(false); }
public static void AssertIsValidForReply(Type messageType) { if (MessageConventionExtensions.IsCommandType(messageType) || MessageConventionExtensions.IsEventType(messageType)) { throw new InvalidOperationException("Reply is neither supported for Commands nor Events. Commands should be sent to their logical owner using bus.Send and bus. Events should be Published with bus.Publish."); } }
/// <summary> /// Enforce messaging rules. Make sure, the message can be used by Bus.Reply. /// </summary> /// <param name="messages">Collection of messages to enforce messaging rules on.</param> public static void AssertIsValidForReply(IEnumerable <object> messages) { if (messages.Any(m => MessageConventionExtensions.IsCommand(m) || MessageConventionExtensions.IsEvent(m))) { throw new InvalidOperationException( "Reply is neither supported for Commands nor Events. Commands should be sent to their logical owner using bus.Send and bus. Events should be Published with bus.Publish."); } }
static TimeSpan TimeToBeReceived(object message) { if (GetDataBusProperties(message).Count == 0) { return(TimeSpan.MaxValue); } return(MessageConventionExtensions.TimeToBeReceivedAction(message.GetType())); }
/// <summary> /// If the type is a message handler, returns all the message types that it handles /// </summary> static IEnumerable <Type> GetMessageTypesIfIsMessageHandler(Type type) { return(from t in type.GetInterfaces() where t.IsGenericType let potentialMessageType = t.GetGenericArguments()[0] where MessageConventionExtensions.IsMessageType(potentialMessageType) || typeof(IHandleMessages <>).MakeGenericType(potentialMessageType).IsAssignableFrom(t) select potentialMessageType); }
public IEnumerable <Type> GetEventsToSubscribe() { return(HandlerRegistry.GetMessageTypes() //get all potential messages .Where(t => !MessageConventionExtensions.IsCommandType(t) && (SubscribePlainMessages || MessageConventionExtensions.IsEventType(t))) //get messages that has routing if required .Where(t => DoNotRequireExplicitRouting || MessageRouter.GetDestinationFor(t).Any()) //get messages with other handlers than sagas if needed .Where(t => !DoNotAutoSubscribeSagas || HandlerRegistry.GetHandlerTypes(t).Any(handler => !typeof(ISaga).IsAssignableFrom(handler))) .ToList()); }
public void Run() { if (Mapper == null) { return; } var messageTypes = Configure.TypesToScan.Where(t => MessageConventionExtensions.IsMessageType(t)).ToList(); Mapper.Initialize(messageTypes); Serializer.Initialize(messageTypes); }
/// <summary> /// Enforce messaging rules. Make sure, the message can be used by pubsub bus methods (<see cref="IBus.Subscribe(System.Type)"/>, <see cref="IBus.Unsubscribe"/> and <see cref="IBus.Publish{T}(T[])"/>).. /// </summary> public static void AssertIsValidForPubSub(Type messageType) { if (MessageConventionExtensions.IsCommandType(messageType)) { throw new InvalidOperationException("Pub/Sub is not supported for Commands. They should be be sent direct to their logical owner."); } if (!MessageConventionExtensions.IsEventType(messageType)) { Log.Info("You are using a basic message to do pub/sub, consider implementing the more specific ICommand and IEvent interfaces to help NServiceBus to enforce messaging best practices for you."); } }
static void ConfigureFinder(Type t) { foreach (Type interfaceType in t.GetInterfaces()) { Type[] args = interfaceType.GetGenericArguments(); if (args.Length != 2) { continue; } Type sagaEntityType = null; Type messageType = null; foreach (Type typ in args) { if (typeof(IContainSagaData).IsAssignableFrom(typ)) { sagaEntityType = typ; } if (MessageConventionExtensions.IsMessageType(typ) || typ == typeof(object)) { messageType = typ; } } if (sagaEntityType == null || messageType == null) { continue; } Type finderType = typeof(IFindSagas <> .Using <>).MakeGenericType(sagaEntityType, messageType); if (!finderType.IsAssignableFrom(t)) { continue; } FinderTypeToSagaEntityTypeLookup[t] = sagaEntityType; MethodInfo method = t.GetMethod("FindBy", new[] { messageType }); IDictionary <Type, MethodInfo> methods; FinderTypeToMessageToMethodInfoLookup.TryGetValue(t, out methods); if (methods == null) { methods = new Dictionary <Type, MethodInfo>(); FinderTypeToMessageToMethodInfoLookup[t] = methods; } methods[messageType] = method; } }
void RegisterMessageOwnersAndBusAddress(IEnumerable <Type> knownMessages) { var unicastConfig = Configure.GetConfigSection <UnicastBusConfig>(); var router = new StaticMessageRouter(knownMessages); var key = typeof(DefaultAutoSubscriptionStrategy).FullName + ".SubscribePlainMessages"; if (SettingsHolder.HasSetting(key)) { router.SubscribeToPlainMessages = SettingsHolder.Get <bool>(key); } Configure.Instance.Configurer.RegisterSingleton <StaticMessageRouter>(router); if (unicastConfig == null) { return; } if (!string.IsNullOrWhiteSpace(unicastConfig.ForwardReceivedMessagesTo)) { var forwardAddress = Address.Parse(unicastConfig.ForwardReceivedMessagesTo); Configure.Instance.Configurer.ConfigureProperty <UnicastBus>(b => b.ForwardReceivedMessagesTo, forwardAddress); Configure.Instance.Configurer.ConfigureProperty <ForwardBehavior>(b => b.ForwardReceivedMessagesTo, forwardAddress); } Configure.Instance.Configurer.ConfigureProperty <UnicastBus>(b => b.TimeToBeReceivedOnForwardedMessages, unicastConfig.TimeToBeReceivedOnForwardedMessages); Configure.Instance.Configurer.ConfigureProperty <ForwardBehavior>(b => b.TimeToBeReceivedOnForwardedMessages, unicastConfig.TimeToBeReceivedOnForwardedMessages); var messageEndpointMappings = unicastConfig.MessageEndpointMappings.Cast <MessageEndpointMapping>() .OrderByDescending(m => m) .ToList(); foreach (var mapping in messageEndpointMappings) { mapping.Configure((messageType, address) => { if (!(MessageConventionExtensions.IsMessageType(messageType) || MessageConventionExtensions.IsEventType(messageType) || MessageConventionExtensions.IsCommandType(messageType))) { return; } if (MessageConventionExtensions.IsEventType(messageType)) { router.RegisterEventRoute(messageType, address); return; } router.RegisterMessageRoute(messageType, address); }); } }
/// <summary> /// Lists all message type for which we have handlers /// </summary> /// <returns></returns> public IEnumerable <Type> GetMessageTypes() { foreach (var handlerType in handlerList.Keys) { foreach (var typeHandled in handlerList[handlerType]) { if (MessageConventionExtensions.IsMessageType(typeHandled)) { yield return(typeHandled); } } } }
static List <PropertyInfo> GetDataBusProperties(object message) { var messageType = message.GetType(); if (!cache.ContainsKey(messageType)) { cache[messageType] = messageType.GetProperties() .Where(property => MessageConventionExtensions.IsDataBusProperty(property)) .ToList(); } return(cache[messageType]); }
public void Start() { if (!Feature.IsEnabled <AutoSubscribe>()) { return; } foreach (var eventType in AutoSubscriptionStrategy.GetEventsToSubscribe() .Where(t => !MessageConventionExtensions.IsInSystemConventionList(t))) //never auto-subscribe system messages { Bus.Subscribe(eventType); Logger.DebugFormat("Auto subscribed to event {0}", eventType); } }
public void Should_cache_the_message_convention() { var timesCalled = 0; MessageConventionExtensions.IsCommandTypeAction = t => { timesCalled++; return(false); }; MessageConventionExtensions.IsCommand(this); Assert.AreEqual(1, timesCalled); MessageConventionExtensions.IsCommand(this); Assert.AreEqual(1, timesCalled); }
public void RegisterMessageType(Type messageType) { var metadata = new MessageMetadata { MessageType = messageType, Recoverable = !DefaultToNonPersistentMessages, TimeToBeReceived = MessageConventionExtensions.TimeToBeReceivedAction(messageType) }; if (MessageConventionExtensions.IsExpressMessageType(messageType)) { metadata.Recoverable = false; } messages[messageType] = metadata; }
static IEnumerable <Type> GetMessagesCorrespondingToFilterOnSaga(Type sagaType, Type filter) { foreach (Type interfaceType in sagaType.GetInterfaces()) { Type[] types = interfaceType.GetGenericArguments(); foreach (Type arg in types) { if (MessageConventionExtensions.IsMessageType(arg)) { if (filter.MakeGenericType(arg) == interfaceType) { yield return(arg); } } } } }
/// <summary> /// If the type is a message handler, returns all the message types that it handles /// </summary> /// <param name="type"></param> /// <returns></returns> static IEnumerable <Type> GetMessageTypesIfIsMessageHandler(Type type) { foreach (var t in type.GetInterfaces().Where(t => t.IsGenericType)) { var potentialMessageType = t.GetGenericArguments().SingleOrDefault(); if (potentialMessageType == null) { continue; } if (MessageConventionExtensions.IsMessageType(potentialMessageType) || typeof(IHandleMessages <>).MakeGenericType(potentialMessageType).IsAssignableFrom(t)) { yield return(potentialMessageType); } } }
/// <summary> /// Specify a test for a message handler specifying a callback to create /// the handler and getting an instance of the bus passed in. /// Useful for handlers based on constructor injection. /// </summary> public static Handler <T> Handler <T>(Func <IBus, T> handlerCreationCallback) { bus = new StubBus(messageCreator); ExtensionMethods.Bus = bus; var handler = handlerCreationCallback.Invoke(bus); var isHandler = (from i in handler.GetType().GetInterfaces() let args = i.GetGenericArguments() where args.Length == 1 where MessageConventionExtensions.IsMessageType(args[0]) where typeof(IHandleMessages <>).MakeGenericType(args[0]).IsAssignableFrom(i) select i).Any(); if (!isHandler) { throw new ArgumentException("The handler object created does not implement IHandleMessages<T>.", "handlerCreationCallback"); } var messageTypes = Configure.TypesToScan.Where(MessageConventionExtensions.IsMessageType).ToList(); return(new Handler <T>(handler, bus, messageCreator, messageTypes)); }
static IEnumerable <Type> GetMessagesCorrespondingToFilterOnSaga(Type sagaType, Type filter) { foreach (var interfaceType in sagaType.GetInterfaces()) { foreach (var argument in interfaceType.GetGenericArguments()) { var genericType = filter.MakeGenericType(argument); var isOfFilterType = genericType == interfaceType; if (!isOfFilterType) { continue; } if (MessageConventionExtensions.IsMessageType(argument)) { yield return(argument); continue; } var message = string.Format("The saga '{0}' implements '{1}' but the message type '{2}' is not classified as a message. You should either use 'Unobtrusive Mode Messages' or the message should implement either 'IMessage', 'IEvent' or 'ICommand'.", sagaType.FullName, genericType.Name, argument.FullName); throw new Exception(message); } } }
private static bool IsWcfService(Type t) { var args = t.GetGenericArguments(); if (args.Length == 2) { if (MessageConventionExtensions.IsMessageType(args[0])) { var wcfType = typeof(WcfService <,>).MakeGenericType(args); if (wcfType.IsAssignableFrom(t)) { return(true); } } } if (t.BaseType != null) { return(IsWcfService(t.BaseType) && !t.IsAbstract); } return(false); }
public void RegisterMessageType(Type messageType) { var metadata = new MessageMetadata { MessageType = messageType, Recoverable = !DefaultToNonPersistentMessages, TimeToBeReceived = MessageConventionExtensions.TimeToBeReceivedAction(messageType) }; if (MessageConventionExtensions.IsExpressMessageType(messageType)) { metadata.Recoverable = false; } //get the parent types var parentMessages = GetParentTypes(messageType) .Where(MessageConventionExtensions.IsMessageType) .OrderByDescending(PlaceInMessageHierarchy) .ToList(); metadata.MessageHierarchy = new[] { messageType }.Concat(parentMessages); messages[messageType] = metadata; }
List <string> GetBaseTypes(object[] messages) { var result = new List <string>(); foreach (var m in messages) { var t = mapper.GetMappedTypeFor(m.GetType()); var baseType = t.BaseType; while (baseType != typeof(object) && baseType != null) { if (MessageConventionExtensions.IsMessageType(baseType)) { if (!result.Contains(baseType.FullName)) { result.Add(baseType.FullName); } } baseType = baseType.BaseType; } foreach (var i in t.GetInterfaces()) { if (MessageConventionExtensions.IsMessageType(i)) { if (!result.Contains(i.FullName)) { result.Add(i.FullName); } } } } return(result); }
public void Should_use_TimeToBeReceived_from_bottom_of_tree() { var timeToBeReceivedAction = MessageConventionExtensions.TimeToBeReceivedAction(typeof(InheritedClassWithAttribute)); Assert.AreEqual(TimeSpan.FromSeconds(2), timeToBeReceivedAction); }
/// <summary> /// Add system messages convention /// </summary> public static Configure AddSystemMessagesAs(this Configure config, Func <Type, bool> definesMessageType) { MessageConventionExtensions.AddSystemMessagesConventions(definesMessageType); return(config); }
/// <summary> /// Invoked before configuration starts. /// </summary> public void Init() { MessageConventionExtensions.AddSystemMessagesConventions(t => typeof(SendEmail) == t); }
public void Init() { MessageConventionExtensions.AddSystemMessagesConventions(t => t.Namespace != null && t.Namespace.StartsWith("ServiceControl.Plugin.") && t.Namespace.EndsWith(".Messages")); }
public void Init() { MessageConventionExtensions.AddSystemMessagesConventions(t => typeof(Messages.ScheduledTask).IsAssignableFrom(t)); }