├── Version.cs ├── AzureNetQ ├── Delegates.cs ├── AutoSubscribe │ ├── IConsume.cs │ ├── IRespond.cs │ ├── IConsumeAsync.cs │ ├── IRespondAsync.cs │ ├── ReadAndDeleteAttribute.cs │ ├── SubscriptionAttribute.cs │ ├── AutoSubscriptionConfiguration.cs │ ├── AutoSubscriberConsumerInfo.cs │ ├── IAutoSubscriberMessageDispatcher.cs │ ├── AutoSubscriberResponderInfo.cs │ └── DefaultAutoSubscriberMessageDispatcher.cs ├── Consumer │ ├── IHandlerCollectionFactory.cs │ ├── HandlerCollectionFactory.cs │ ├── IReceiveRegistration.cs │ ├── IHandlerRegistration.cs │ ├── IHandlerCollection.cs │ └── HandlerCollection.cs ├── Producer │ ├── RpcKey.cs │ ├── ResponseAction.cs │ ├── IRpc.cs │ ├── ISendReceive.cs │ └── SendReceive.cs ├── packages.config ├── IAzureNetQLogger.cs ├── ISerializer.cs ├── FluentConfiguration │ ├── IPublishConfiguration.cs │ ├── IRequestConfiguration.cs │ ├── IRespondConfiguration.cs │ └── ISubscriptionConfiguration.cs ├── Loggers │ ├── NullLogger.cs │ ├── DelegateLogger.cs │ └── ConsoleLogger.cs ├── ExceptionHandler.cs ├── TaskHelpers.cs ├── BrokeredMessageExtensions.cs ├── IConnectionConfiguration.cs ├── Properties │ └── AssemblyInfo.cs ├── AzureBusFactory.cs ├── MessageExtensions.cs ├── TypeNameSerializer.cs ├── AzureNetQSettings.cs ├── JsonSerializer.cs ├── AzureNetQException.cs ├── Conventions.cs ├── NonGeneric │ └── NonGenericExtensions.cs ├── app.config ├── IBus.cs ├── AzureNetQ.csproj ├── Preconditions.cs ├── Settings.StyleCop └── AzureAdvancedBus.cs ├── AzureNetQ.Tests.PublishSubscribe ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── AzureNetQ.Tests.PublishSubscribe.csproj └── Settings.StyleCop ├── AzureNetQ.Tests.SimpleRequester ├── ILatencyRecorder.cs ├── app.config ├── Properties │ └── AssemblyInfo.cs ├── LatencyRecorder.cs ├── AzureNetQ.Tests.SimpleRequester.csproj ├── Program.cs └── Settings.StyleCop ├── AzureNetQ.Tests ├── packages.config ├── Properties │ └── AssemblyInfo.cs └── AzureNetQ.Tests.csproj ├── .gitignore ├── AzureNetQ.Tests.SimpleService ├── app.config ├── Properties │ └── AssemblyInfo.cs ├── AzureNetQ.Tests.SimpleService.csproj ├── Program.cs └── Settings.StyleCop ├── AzureNetQ.Tests.SendReceive ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── Program.cs ├── AzureNetQ.Tests.SendReceive.csproj └── Settings.StyleCop ├── .gitattributes ├── AzureNetQ.nuspec ├── AzureNetQ.Tests.Messages ├── Messages.cs ├── Properties │ └── AssemblyInfo.cs └── AzureNetQ.Tests.Messages.csproj ├── licence.txt ├── README.md ├── Packages.dgml └── AzureNetQ.sln /Version.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyVersion("0.0.1.0")] 5 | [assembly: CLSCompliant(true)] -------------------------------------------------------------------------------- /AzureNetQ/Delegates.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | public delegate string SubsriberNameFromDelegate(Delegate @delegate); 6 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/IConsume.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | public interface IConsume where T : class 4 | { 5 | void Consume(T message); 6 | } 7 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/IRespond.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | public interface IRespond where T : class 4 | { 5 | TResponse Respond(T message); 6 | } 7 | } -------------------------------------------------------------------------------- /AzureNetQ/Consumer/IHandlerCollectionFactory.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace AzureNetQ.Consumer 3 | { 4 | public interface IHandlerCollectionFactory 5 | { 6 | IHandlerCollection CreateHandlerCollection(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /AzureNetQ/Producer/RpcKey.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Producer 2 | { 3 | using System; 4 | 5 | internal struct RpcKey 6 | { 7 | public Type Request; 8 | 9 | public Type Response; 10 | } 11 | } -------------------------------------------------------------------------------- /AzureNetQ.Tests.PublishSubscribe/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/IConsumeAsync.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System.Threading.Tasks; 4 | 5 | public interface IConsumeAsync where T : class 6 | { 7 | Task Consume(T message); 8 | } 9 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/IRespondAsync.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System.Threading.Tasks; 4 | 5 | public interface IRespondAsync where T : class 6 | { 7 | Task Respond(T message); 8 | } 9 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/ReadAndDeleteAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | [AttributeUsage(AttributeTargets.Method)] 7 | public class ReceiveAndDeleteAttribute : Attribute 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /AzureNetQ/Producer/ResponseAction.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Producer 2 | { 3 | using System; 4 | 5 | using Microsoft.ServiceBus.Messaging; 6 | 7 | internal class ResponseAction 8 | { 9 | public Action OnSuccess { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/ILatencyRecorder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AzureNetQ.Tests.SimpleRequester 4 | { 5 | public interface ILatencyRecorder : IDisposable 6 | { 7 | void RegisterRequest(long requestId); 8 | void RegisterResponse(long responseId); 9 | } 10 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/SubscriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | [AttributeUsage(AttributeTargets.Method)] 7 | public class SubscriptionAttribute : Attribute 8 | { 9 | public string Name { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AzureNetQ.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /AzureNetQ/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AzureNetQ/IAzureNetQLogger.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | public interface IAzureNetQLogger 6 | { 7 | void DebugWrite(string format, params object[] args); 8 | 9 | void InfoWrite(string format, params object[] args); 10 | 11 | void ErrorWrite(string format, params object[] args); 12 | 13 | void ErrorWrite(Exception exception); 14 | } 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj 2 | [Bb]in 3 | *.user 4 | *.suo 5 | *.[Cc]ache 6 | *.bak 7 | *.ncb 8 | *.log 9 | *.DS_Store 10 | [Tt]humbs.db 11 | _ReSharper.* 12 | 13 | # Ignore NCrunch cache files. 14 | *.crunchproject.local.xml 15 | *.crunchsolution.local.xml 16 | *.ncrunchproject 17 | *.ncrunchsolution 18 | 19 | # Ignore test output 20 | TestResult.xml 21 | 22 | # Ignore NuGet package files. 23 | *.nupkg 24 | 25 | *.userprefs 26 | test-results 27 | 28 | # NuGet Packages Directory 29 | packages -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleService/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SendReceive/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AzureNetQ/ISerializer.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | public interface ISerializer 4 | { 5 | byte[] MessageToBytes(T message) where T : class; 6 | 7 | string MessageToString(T message) where T : class; 8 | 9 | T BytesToMessage(byte[] bytes); 10 | 11 | T StringToMessage(string content); 12 | 13 | object BytesToMessage(string typeName, byte[] bytes); 14 | 15 | object StringToMessage(string typeName, string content); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AzureNetQ/Consumer/HandlerCollectionFactory.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Consumer 2 | { 3 | public class HandlerCollectionFactory : IHandlerCollectionFactory 4 | { 5 | private readonly IAzureNetQLogger logger; 6 | 7 | public HandlerCollectionFactory(IAzureNetQLogger logger) 8 | { 9 | this.logger = logger; 10 | } 11 | 12 | public IHandlerCollection CreateHandlerCollection() 13 | { 14 | return new HandlerCollection(this.logger); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AzureNetQ/FluentConfiguration/IPublishConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.FluentConfiguration 2 | { 3 | public interface IPublishConfiguration 4 | { 5 | IPublishConfiguration WithMessageId(string messageId); 6 | } 7 | 8 | public class PublishConfiguration : IPublishConfiguration 9 | { 10 | public string MessageId { get; set; } 11 | 12 | public IPublishConfiguration WithMessageId(string messageId) 13 | { 14 | this.MessageId = messageId; 15 | return this; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /AzureNetQ/FluentConfiguration/IRequestConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.FluentConfiguration 2 | { 3 | public interface IRequestConfiguration 4 | { 5 | int? Affinity { get; } 6 | 7 | IRequestConfiguration WithAffinity(int? affinity); 8 | } 9 | 10 | public class RequestConfiguration : IRequestConfiguration 11 | { 12 | public int? Affinity { get; private set; } 13 | 14 | public IRequestConfiguration WithAffinity(int? affinity) 15 | { 16 | this.Affinity = affinity; 17 | return this; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /AzureNetQ/Loggers/NullLogger.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Loggers 2 | { 3 | using System; 4 | 5 | /// 6 | /// noop logger 7 | /// 8 | public class NullLogger : IAzureNetQLogger 9 | { 10 | public void DebugWrite(string format, params object[] args) 11 | { 12 | } 13 | 14 | public void InfoWrite(string format, params object[] args) 15 | { 16 | } 17 | 18 | public void ErrorWrite(string format, params object[] args) 19 | { 20 | } 21 | 22 | public void ErrorWrite(Exception exception) 23 | { 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /AzureNetQ/ExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using Microsoft.ServiceBus.Messaging; 4 | 5 | public interface IExceptionHandler 6 | { 7 | void ExceptionReceived(object sender, ExceptionReceivedEventArgs args); 8 | } 9 | 10 | public class ExceptionHandler : IExceptionHandler 11 | { 12 | private readonly IAzureNetQLogger logger; 13 | 14 | public ExceptionHandler(IAzureNetQLogger logger) 15 | { 16 | this.logger = logger; 17 | } 18 | 19 | public void ExceptionReceived(object sender, ExceptionReceivedEventArgs args) 20 | { 21 | this.logger.ErrorWrite(args.Exception); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /AzureNetQ/TaskHelpers.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | public static class TaskHelpers 7 | { 8 | public static Task ExecuteSynchronously(Action action) 9 | { 10 | var tcs = new TaskCompletionSource(); 11 | try 12 | { 13 | action(); 14 | tcs.SetResult(new NullStruct()); 15 | } 16 | catch (Exception e) 17 | { 18 | tcs.SetException(e); 19 | } 20 | 21 | return tcs.Task; 22 | } 23 | 24 | private struct NullStruct 25 | { 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/AutoSubscriptionConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | 5 | public interface IAutoSubscriptionConfiguration 6 | { 7 | Func AffinityResolver { get; set; } 8 | 9 | IAutoSubscriptionConfiguration WithAffinityResolver(Func affinityResolver); 10 | } 11 | 12 | public class AutoSubscriptionConfiguration : IAutoSubscriptionConfiguration 13 | { 14 | public Func AffinityResolver { get; set; } 15 | 16 | public IAutoSubscriptionConfiguration WithAffinityResolver(Func affinityResolver) 17 | { 18 | this.AffinityResolver = affinityResolver; 19 | return this; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/AutoSubscriberConsumerInfo.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | public class AutoSubscriberConsumerInfo 7 | { 8 | public readonly Type ConcreteType; 9 | public readonly Type InterfaceType; 10 | public readonly Type MessageType; 11 | 12 | public AutoSubscriberConsumerInfo(Type concreteType, Type interfaceType, Type messageType) 13 | { 14 | Preconditions.CheckNotNull(concreteType, "concreteType"); 15 | Preconditions.CheckNotNull(interfaceType, "interfaceType"); 16 | Preconditions.CheckNotNull(messageType, "messageType"); 17 | 18 | this.ConcreteType = concreteType; 19 | this.InterfaceType = interfaceType; 20 | this.MessageType = messageType; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /AzureNetQ/BrokeredMessageExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using Microsoft.ServiceBus.Messaging; 4 | 5 | internal static class BrokeredMessageExtensions 6 | { 7 | private const string MessageTypePropertyKey = "Type"; 8 | 9 | public static void SetMessageType(this BrokeredMessage message, string typeName) 10 | { 11 | Preconditions.CheckNotNull(message, "message"); 12 | Preconditions.CheckNotNull(typeName, "typeName"); 13 | 14 | message.Properties[MessageTypePropertyKey] = typeName; 15 | } 16 | 17 | public static string GetMessageType(this BrokeredMessage message) 18 | { 19 | Preconditions.CheckNotNull(message, "message"); 20 | 21 | object prop; 22 | return message.Properties.TryGetValue(MessageTypePropertyKey, out prop) ? prop.ToString() : null; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/IAutoSubscriberMessageDispatcher.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System.Threading.Tasks; 4 | 5 | public interface IAutoSubscriberMessageDispatcher 6 | { 7 | void Dispatch(TMessage message) 8 | where TMessage : class 9 | where TConsumer : IConsume; 10 | 11 | Task DispatchAsync(TMessage message) 12 | where TMessage : class 13 | where TConsumer : IConsumeAsync; 14 | 15 | TResponse Handle(TMessage message) 16 | where TMessage : class 17 | where TResponder : IRespond; 18 | 19 | Task HandleAsync(TMessage message) 20 | where TMessage : class 21 | where TResponder : IRespondAsync; 22 | } 23 | } -------------------------------------------------------------------------------- /AzureNetQ.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.2.0.1 5 | Roysvork 6 | Roysvork 7 | AzureNetQ 8 | AzureNetQ 9 | false 10 | AzureNetQ is a client API for Microsoft Azure Service Bus & Service Bus for Windows on .NET 11 | Pete Smith 2014 12 | http://roysvork.github.io/AzureNetQ 13 | https://github.com/roysvork/AzureNetQ/blob/master/licence.txt 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.Messages/Messages.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Tests.Messages 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | public class TestRequestMessage 7 | { 8 | public long Id { get; set; } 9 | public string Text { get; set; } 10 | public bool CausesExceptionInServer { get; set; } 11 | public string ExceptionInServerMessage { get; set; } 12 | public bool CausesServerToTakeALongTimeToRespond { get; set; } 13 | } 14 | 15 | [Serializable] 16 | public class TestResponseMessage 17 | { 18 | public long Id { get; set; } 19 | public string Text { get; set; } 20 | } 21 | 22 | [Serializable] 23 | public class TestAsyncRequestMessage 24 | { 25 | public long Id { get; set; } 26 | public string Text { get; set; } 27 | } 28 | 29 | [Serializable] 30 | public class TestAsyncResponseMessage 31 | { 32 | public long Id { get; set; } 33 | public string Text { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /AzureNetQ/Consumer/IReceiveRegistration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Consumer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | public interface IReceiveRegistration 7 | { 8 | /// 9 | /// Add an asychronous message handler to this receiver 10 | /// 11 | /// The type of message to receive 12 | /// The message handler 13 | /// 'this' for fluent configuration 14 | IReceiveRegistration Add(Func onMessage) where T : class; 15 | 16 | /// 17 | /// Add a message handler to this receiver 18 | /// 19 | /// The type of message to receive 20 | /// The message handler 21 | /// 'this' for fluent configuration 22 | IReceiveRegistration Add(Action onMessage) where T : class; 23 | } 24 | } -------------------------------------------------------------------------------- /AzureNetQ/Producer/IRpc.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Producer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | using AzureNetQ.FluentConfiguration; 7 | 8 | /// 9 | /// An RPC style request-response pattern 10 | /// 11 | public interface IRpc 12 | { 13 | Task Request(TRequest request) where TRequest : class 14 | where TResponse : class; 15 | 16 | Task Request(TRequest request, Action configure) 17 | where TRequest : class 18 | where TResponse : class; 19 | 20 | IDisposable Respond(Func> responder) 21 | where TRequest : class where TResponse : class; 22 | 23 | IDisposable Respond(Func> responder, Action configure) 24 | where TRequest : class 25 | where TResponse : class; 26 | } 27 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/AutoSubscriberResponderInfo.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | public class AutoSubscriberResponderInfo 7 | { 8 | public readonly Type ConcreteType; 9 | 10 | public readonly Type InterfaceType; 11 | 12 | public readonly Type MessageType; 13 | 14 | public readonly Type ResponseType; 15 | 16 | public AutoSubscriberResponderInfo(Type concreteType, Type interfaceType, Type messageType, Type responseType) 17 | { 18 | Preconditions.CheckNotNull(concreteType, "concreteType"); 19 | Preconditions.CheckNotNull(interfaceType, "interfaceType"); 20 | Preconditions.CheckNotNull(messageType, "messageType"); 21 | Preconditions.CheckNotNull(responseType, "responseType"); 22 | 23 | this.ConcreteType = concreteType; 24 | this.InterfaceType = interfaceType; 25 | this.MessageType = messageType; 26 | this.ResponseType = responseType; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /AzureNetQ/IConnectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | public interface IConnectionConfiguration 6 | { 7 | ushort Timeout { get; set; } 8 | 9 | int PrefetchCount { get; set; } 10 | 11 | int MaxConcurrentCalls { get; set; } 12 | 13 | TimeSpan BatchingInterval { get; set; } 14 | 15 | string ConnectionString { get; set; } 16 | } 17 | 18 | public class ConnectionConfiguration : IConnectionConfiguration 19 | { 20 | public ConnectionConfiguration() 21 | { 22 | this.Timeout = 30; 23 | this.PrefetchCount = 0; 24 | this.MaxConcurrentCalls = 1; 25 | this.BatchingInterval = TimeSpan.FromMilliseconds(20); 26 | } 27 | 28 | public TimeSpan BatchingInterval { get; set; } 29 | 30 | public string ConnectionString { get; set; } 31 | 32 | public ushort Timeout { get; set; } 33 | 34 | public int PrefetchCount { get; set; } 35 | 36 | public int MaxConcurrentCalls { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AzureNetQ.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AzureNetQ.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("AzureNetQ")] 11 | [assembly: AssemblyProduct("AzureNetQ.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © AzureNetQ 2011")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("1dff2e31-d6a3-4744-b608-0607a3b08605")] 23 | 24 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AzureNetQ.Tests.SimpleService")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("AzureNetQ")] 11 | [assembly: AssemblyProduct("AzureNetQ.Tests.SimpleService")] 12 | [assembly: AssemblyCopyright("Copyright © AzureNetQ 2011")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("eb936393-fad8-4727-aafe-532b48b00142")] 23 | 24 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Mike Hadlow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /AzureNetQ/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AzureNetQ")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("AzureNetQ")] 11 | [assembly: AssemblyProduct("AzureNetQ")] 12 | [assembly: AssemblyCopyright("Copyright © AzureNetQ 2011")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("a306e985-0fcf-4cc6-a1a3-d57214d1ea40")] 23 | 24 | [assembly: AssemblyVersionAttribute("0.2.0.*")] 25 | [assembly: AssemblyFileVersionAttribute("0.2.0.1")] 26 | -------------------------------------------------------------------------------- /AzureNetQ/FluentConfiguration/IRespondConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.FluentConfiguration 2 | { 3 | using System; 4 | 5 | public interface IRespondConfiguration 6 | { 7 | Func AffinityResolver { get; } 8 | 9 | int RequeueDelay { get; set; } 10 | 11 | IRespondConfiguration WithAffinityResolver(Func affinity); 12 | 13 | IRespondConfiguration WithRequeueDelay(int requeueDelay); 14 | } 15 | 16 | public class RespondConfiguration : IRespondConfiguration 17 | { 18 | public RespondConfiguration() 19 | { 20 | this.RequeueDelay = 5; 21 | } 22 | 23 | public Func AffinityResolver { get; private set; } 24 | 25 | public int RequeueDelay { get; set; } 26 | 27 | public IRespondConfiguration WithAffinityResolver(Func affinity) 28 | { 29 | this.AffinityResolver = affinity; 30 | return this; 31 | } 32 | 33 | public IRespondConfiguration WithRequeueDelay(int requeueDelay) 34 | { 35 | this.RequeueDelay = requeueDelay; 36 | return this; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /AzureNetQ/Consumer/IHandlerRegistration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Consumer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | public interface IHandlerRegistration 7 | { 8 | /// 9 | /// Set to true if the handler collection should throw an AzureNetQException when no 10 | /// matching handler is found, or false if it should return a noop handler. 11 | /// Default is true. 12 | /// 13 | bool ThrowOnNoMatchingHandler { get; set; } 14 | 15 | /// 16 | /// Add an asynchronous handler 17 | /// 18 | /// The message type 19 | /// The handler 20 | /// 21 | IHandlerRegistration Add(Func handler) 22 | where T : class; 23 | 24 | /// 25 | /// Add a synchronous handler 26 | /// 27 | /// The message type 28 | /// The handler 29 | /// 30 | IHandlerRegistration Add(Action handler) 31 | where T : class; 32 | } 33 | } -------------------------------------------------------------------------------- /AzureNetQ/Consumer/IHandlerCollection.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Consumer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | public interface IHandlerCollection : IHandlerRegistration 7 | { 8 | /// 9 | /// Retrieve a handler from the collection. 10 | /// If a matching handler cannot be found, the handler collection will either throw 11 | /// an AzureNetQException, or return null, depending on the value of the 12 | /// ThrowOnNoMatchingHandler property. 13 | /// 14 | /// The type of handler to return 15 | /// The handler 16 | Func GetHandler() 17 | where T : class; 18 | 19 | /// 20 | /// Retrieve a handler from the collection. 21 | /// If a matching handler cannot be found, the handler collection will either throw 22 | /// an AzureNetQException, or return null, depending on the value of the 23 | /// ThrowOnNoMatchingHandler property. 24 | /// 25 | /// The type of handler to return 26 | /// The handler 27 | dynamic GetHandler(Type messageType); 28 | } 29 | } -------------------------------------------------------------------------------- /AzureNetQ/AzureBusFactory.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using Microsoft.WindowsAzure; 4 | 5 | public static class AzureBusFactory 6 | { 7 | public static IBus CreateBus() 8 | { 9 | return CreateBus(new AzureNetQSettings()); 10 | } 11 | 12 | public static IBus CreateBus(string connectionString) 13 | { 14 | return CreateBus(connectionString, new AzureNetQSettings()); 15 | } 16 | 17 | public static IBus CreateBus(AzureNetQSettings settings) 18 | { 19 | var connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString"); 20 | return CreateBus(connectionString, settings); 21 | } 22 | 23 | public static IBus CreateBus(string connectionString, AzureNetQSettings settings) 24 | { 25 | settings.ConnectionConfiguration.ConnectionString = connectionString; 26 | 27 | return new AzureBus( 28 | settings.Logger(), 29 | settings.Conventions(), 30 | settings.Rpc(), 31 | settings.SendAndReceive(), 32 | settings.AzureAdvancedBus.Value, 33 | settings.ConnectionConfiguration, 34 | settings.Serializer()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /AzureNetQ/MessageExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Threading; 6 | 7 | using Microsoft.ServiceBus.Messaging; 8 | 9 | internal static class MessageExtensions 10 | { 11 | public static bool ShouldBeFilteredByAffinity( 12 | this BrokeredMessage message, 13 | Func affinity, 14 | out int messageAffinity) 15 | { 16 | messageAffinity = 0; 17 | return affinity != null && message.Properties.ContainsKey("Affinity") 18 | && int.TryParse(message.Properties["Affinity"].ToString(), out messageAffinity); 19 | } 20 | 21 | public static TimerCallback KeepLockAlive(this BrokeredMessage message, IAzureNetQLogger logger) 22 | { 23 | return state => message.RenewLockAsync().ContinueWith( 24 | t => 25 | { 26 | if (t.Exception == null) 27 | { 28 | return; 29 | } 30 | 31 | var exception = t.Exception.Flatten().InnerExceptions.First(); 32 | if (exception is MessageLockLostException) 33 | { 34 | return; 35 | } 36 | 37 | ((Timer)state).Dispose(); 38 | logger.ErrorWrite(exception); 39 | }); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /AzureNetQ.Tests.PublishSubscribe/Program.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Tests.PublishSubscribe 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | using AzureNetQ.NonGeneric; 7 | 8 | public class Program 9 | { 10 | private IBus bus; 11 | 12 | public static void Main(string[] args) 13 | { 14 | new Program().Run(); 15 | } 16 | 17 | private void Run() 18 | { 19 | this.bus = AzureBusFactory.CreateBus("Endpoint=sb://servicebus/ServiceBusDefaultNamespace;StsEndpoint=https://servicebus:10355/ServiceBusDefaultNamespace;RuntimePort=10354;ManagementPort=10355"); 20 | 21 | this.bus.SubscribeAsync( 22 | typeof(TestMessage), 23 | obj => Task.Factory.StartNew(() => Console.WriteLine("Handler Received message: {0}", ((TestMessage)obj).Text))); 24 | 25 | Console.WriteLine("Type a message or 'q' to quit."); 26 | 27 | string text = null; 28 | while ((text = Console.ReadLine()) != "q") 29 | { 30 | this.bus.Publish( 31 | typeof(TestMessage), 32 | new TestMessage 33 | { 34 | Text = text 35 | }); 36 | } 37 | 38 | this.bus.Dispose(); 39 | } 40 | } 41 | 42 | [Serializable] 43 | public class TestMessage 44 | { 45 | public string Text { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.Messages/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AzureNetQ.Tests.Messages")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AzureNetQ.Tests.Messages")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a52e0c56-48be-4c07-87fc-01c83b7398b2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SendReceive/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AzureNetQ.Tests.SendReceive")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AzureNetQ.Tests.SendReceive")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5fb49418-75c0-4d24-9689-5ce23c2f7e88")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AzureNetQ.Tests.SimpleRequester")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AzureNetQ.Tests.SimpleRequester")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9509a2f9-b488-44f9-ac31-4fee3f81ce16")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.PublishSubscribe/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AzureNetQ.Tests.PublishSubscribe")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AzureNetQ.Tests.PublishSubscribe")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("597d801d-a1bc-4f7a-ab00-36eb16f671e0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AzureNetQ/TypeNameSerializer.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | public interface ITypeNameSerializer 6 | { 7 | string Serialize(Type type); 8 | 9 | Type DeSerialize(string typeName); 10 | } 11 | 12 | public class TypeNameSerializer : ITypeNameSerializer 13 | { 14 | public Type DeSerialize(string typeName) 15 | { 16 | var nameParts = typeName.Split('-'); 17 | if (nameParts.Length != 2) 18 | { 19 | throw new AzureNetQException( 20 | "type name {0}, is not a valid AzureNetQ type name. Expected Type:Assembly", 21 | typeName); 22 | } 23 | 24 | var type = Type.GetType(nameParts[0] + ", " + nameParts[1]); 25 | if (type == null) 26 | { 27 | throw new AzureNetQException( 28 | "Cannot find type {0}", 29 | typeName); 30 | } 31 | 32 | return type; 33 | } 34 | 35 | public string Serialize(Type type) 36 | { 37 | Preconditions.CheckNotNull(type, "type"); 38 | var typeName = type.FullName + "-" + type.Assembly.GetName().Name; 39 | if (typeName.Length > 255) 40 | { 41 | throw new AzureNetQException( 42 | "The serialized name of type '{0}' exceeds the AMQP" 43 | + "maximum short string lengh of 255 characters.", 44 | type.Name); 45 | } 46 | 47 | return typeName; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /AzureNetQ/AutoSubscribe/DefaultAutoSubscriberMessageDispatcher.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.AutoSubscribe 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | public class DefaultAutoSubscriberMessageDispatcher : IAutoSubscriberMessageDispatcher 7 | { 8 | public void Dispatch(TMessage message) 9 | where TMessage : class 10 | where TConsumer : IConsume 11 | { 12 | var consumer = (IConsume)Activator.CreateInstance(typeof(TConsumer)); 13 | 14 | consumer.Consume(message); 15 | } 16 | 17 | public Task DispatchAsync(TMessage message) 18 | where TMessage : class 19 | where TConsumer : IConsumeAsync 20 | { 21 | var consumer = (IConsumeAsync)Activator.CreateInstance(typeof(TConsumer)); 22 | 23 | return consumer.Consume(message); 24 | } 25 | 26 | public TResponse Handle(TMessage message) 27 | where TMessage : class 28 | where TResponder : IRespond 29 | { 30 | var responder = (IRespond)Activator.CreateInstance(typeof(TResponder)); 31 | return responder.Respond(message); 32 | } 33 | 34 | public Task HandleAsync(TMessage message) 35 | where TMessage : class 36 | where TResponder : IRespondAsync 37 | { 38 | var responder = (IRespondAsync)Activator.CreateInstance(typeof(TResponder)); 39 | return responder.Respond(message); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /AzureNetQ/AzureNetQSettings.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | using AzureNetQ.Consumer; 6 | using AzureNetQ.Loggers; 7 | using AzureNetQ.Producer; 8 | 9 | public class AzureNetQSettings 10 | { 11 | public AzureNetQSettings() 12 | { 13 | this.Logger = () => new ConsoleLogger(); 14 | this.Conventions = () => new Conventions(new TypeNameSerializer()); 15 | this.ConnectionConfiguration = new ConnectionConfiguration(); 16 | this.Serializer = () => new JsonSerializer(new TypeNameSerializer()); 17 | 18 | this.AzureAdvancedBus = new Lazy( 19 | () => new AzureAdvancedBus(this.Logger(), this.ConnectionConfiguration)); 20 | 21 | this.Rpc = 22 | () => 23 | new Rpc( 24 | this.Conventions(), 25 | this.AzureAdvancedBus.Value, 26 | this.ConnectionConfiguration, 27 | this.Serializer(), 28 | this.Logger()); 29 | 30 | this.SendAndReceive = 31 | () => 32 | new SendReceive( 33 | this.AzureAdvancedBus.Value, 34 | this.ConnectionConfiguration, 35 | new HandlerCollectionFactory(this.Logger()), 36 | new TypeNameSerializer(), 37 | this.Serializer()); 38 | } 39 | 40 | public Lazy AzureAdvancedBus { get; set; } 41 | 42 | public IConnectionConfiguration ConnectionConfiguration { get; set; } 43 | 44 | public Func Logger { get; set; } 45 | 46 | public Func Conventions { get; set; } 47 | 48 | public Func Rpc { get; set; } 49 | 50 | public Func SendAndReceive { get; set; } 51 | 52 | public Func Serializer { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /AzureNetQ/Loggers/DelegateLogger.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Loggers 2 | { 3 | using System; 4 | 5 | public class DelegateLogger : IAzureNetQLogger 6 | { 7 | public DelegateLogger() 8 | { 9 | this.DefaultWrite = (s, o) => { }; 10 | } 11 | 12 | public Action DefaultWrite { get; set; } 13 | 14 | public Action DebugWriteDelegate { get; set; } 15 | 16 | public Action InfoWriteDelegate { get; set; } 17 | 18 | public Action ErrorWriteDelegate { get; set; } 19 | 20 | public void DebugWrite(string format, params object[] args) 21 | { 22 | if (this.DebugWriteDelegate == null) 23 | { 24 | this.DefaultWrite(format, args); 25 | } 26 | else 27 | { 28 | this.DebugWriteDelegate(format, args); 29 | } 30 | } 31 | 32 | public void InfoWrite(string format, params object[] args) 33 | { 34 | if (this.InfoWriteDelegate == null) 35 | { 36 | this.DefaultWrite(format, args); 37 | } 38 | else 39 | { 40 | this.InfoWriteDelegate(format, args); 41 | } 42 | } 43 | 44 | public void ErrorWrite(string format, params object[] args) 45 | { 46 | if (this.ErrorWriteDelegate == null) 47 | { 48 | this.DefaultWrite(format, args); 49 | } 50 | else 51 | { 52 | this.ErrorWriteDelegate(format, args); 53 | } 54 | } 55 | 56 | public void ErrorWrite(Exception exception) 57 | { 58 | if (this.ErrorWriteDelegate == null) 59 | { 60 | this.DefaultWrite(exception.ToString(), new object[0]); 61 | } 62 | else 63 | { 64 | this.ErrorWriteDelegate(exception.ToString(), new object[0]); 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /AzureNetQ/Loggers/ConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Loggers 2 | { 3 | using System; 4 | 5 | public class ConsoleLogger : IAzureNetQLogger 6 | { 7 | public ConsoleLogger() 8 | { 9 | this.Debug = true; 10 | this.Info = true; 11 | this.Error = true; 12 | } 13 | 14 | public bool Debug { get; set; } 15 | 16 | public bool Info { get; set; } 17 | 18 | public bool Error { get; set; } 19 | 20 | public void DebugWrite(string format, params object[] args) 21 | { 22 | if (!this.Debug) 23 | { 24 | return; 25 | } 26 | 27 | this.SafeConsoleWrite(DateTime.UtcNow.ToString("dd-MM-yyyy hh:mm:ss") + " DEBUG: " + format, args); 28 | } 29 | 30 | public void InfoWrite(string format, params object[] args) 31 | { 32 | if (!this.Info) 33 | { 34 | return; 35 | } 36 | 37 | this.SafeConsoleWrite(DateTime.UtcNow.ToString("dd-MM-yyyy hh:mm:ss") + " INFO: " + format, args); 38 | } 39 | 40 | public void ErrorWrite(string format, params object[] args) 41 | { 42 | if (!this.Error) 43 | { 44 | return; 45 | } 46 | 47 | this.SafeConsoleWrite(DateTime.UtcNow.ToString("dd-MM-yyyy hh:mm:ss") + " ERROR: " + format, args); 48 | } 49 | 50 | public void SafeConsoleWrite(string format, params object[] args) 51 | { 52 | // even a zero length args paramter causes WriteLine to interpret 'format' as 53 | // a format string. Rather than escape JSON, better to check the intention of 54 | // the caller. 55 | if (args.Length == 0) 56 | { 57 | Console.WriteLine(format); 58 | } 59 | else 60 | { 61 | Console.WriteLine(format, args); 62 | } 63 | } 64 | 65 | public void ErrorWrite(Exception exception) 66 | { 67 | Console.WriteLine(exception.ToString()); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /AzureNetQ/Producer/ISendReceive.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Producer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | using AzureNetQ.Consumer; 7 | 8 | public interface ISendReceive 9 | { 10 | /// 11 | /// Send a message to the specified queue 12 | /// 13 | /// The type of message to send 14 | /// The queue to send the message to 15 | /// The message to send 16 | void Send(string queue, T message) where T : class; 17 | 18 | /// 19 | /// Receive a message from the specified queue 20 | /// 21 | /// The type of message to receive 22 | /// The queue to receive from 23 | /// The synchronous function that handles the message 24 | /// Consumer cancellation. Call Dispose to stop consuming 25 | IDisposable Receive(string queue, Action onMessage) where T : class; 26 | 27 | /// 28 | /// Receive a message from the specified queue 29 | /// 30 | /// The type of message to receive 31 | /// The queue to receive from 32 | /// The asynchronous function that handles the message 33 | /// Consumer cancellation. Call Dispose to stop consuming 34 | IDisposable Receive(string queue, Func onMessage) where T : class; 35 | 36 | /// 37 | /// Receive a message from the specified queue. Dispatch them to the given handlers 38 | /// 39 | /// The queue to take messages from 40 | /// A function to add handlers 41 | /// Consumer cancellation. Call Dispose to stop consuming 42 | IDisposable Receive(string queue, Action addHandlers); 43 | } 44 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![AzureNetQ Logo](https://raw.githubusercontent.com/Roysvork/AzureNetQ/gh-pages/design/logo_design_150.png) 2 | 3 | A Nice .NET API for Microsoft Azure Service Bus & Service Bus for Windows. **Please note that documentation is currently under construction** 4 | 5 | * **[Homepage](http://roysvork.github.io/AzureNetQ)** 6 | * **[Documentation](https://github.com/roysvork/AzureNetQ/wiki/Introduction)** 7 | * **[NuGet](http://nuget.org/List/Packages/AzureNetQ)** 8 | * **[EasyNetQ Project](http://github.com/mikehadlow/EasyNetQ)** 9 | * **[EasyNetQ Discussion Group](https://groups.google.com/group/easynetq)** 10 | 11 | Goals: 12 | 13 | 1. To make working with Microsoft Service Bus on .NET as easy as possible. 14 | 2. To build an API that is close to interchangable with EasyNetQ. 15 | 16 | To connect to Service Bus... 17 | 18 | var bus = AzureBusFactory.CreateBus("Endpoint=sb://servicebus/ServiceBusDefaultNamespace;StsEndpoint=https://servicebus:10355/ServiceBusDefaultNamespace;RuntimePort=10354;ManagementPort=10355"); 19 | 20 | To publish a message... 21 | 22 | bus.Publish(message); 23 | 24 | To subscribe to a message... 25 | 26 | bus.Subscribe(msg => Console.WriteLine(msg.Text)); 27 | 28 | Remote procedure call... 29 | 30 | var request = new TestRequestMessage {Text = "Hello from the client! "}; 31 | bus.Request(request, response => 32 | Console.WriteLine("Got response: '{0}'", response.Text)); 33 | 34 | RPC server... 35 | 36 | bus.Respond(request => 37 | new TestResponseMessage{ Text = request.Text + " all done!" }); 38 | 39 | 40 | ## Getting started 41 | 42 | Just open AzureNetQ.sln in VisualStudio 2013 and build. 43 | 44 | All the required dependencies for the solution file to build the software are included. To run the explicit tests that send messages you will have to be running the AzureNetQ.Tests.SimpleService application and have a working Service Bus for Windows install (Blog post coming) 45 | 46 | ## Mono specific 47 | 48 | Unlike EasyNetQ, AzureNetQ has not yet been tested on Mono. If you would like to help with this, please get in touch with @roysvork on twitter! 49 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SendReceive/Program.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Tests.SendReceive 2 | { 3 | using System; 4 | 5 | public class Program 6 | { 7 | private const string SendReceiveQueue = "azurenetq.tests.sendreceive"; 8 | 9 | private const string AuditQueue = "azurenetq.tests.sendreceive.audit"; 10 | 11 | private IBus bus; 12 | 13 | public static void Main(string[] args) 14 | { 15 | new Program().Run(); 16 | } 17 | 18 | private void Run() 19 | { 20 | this.bus = AzureBusFactory.CreateBus(); 21 | 22 | this.bus.Receive( 23 | SendReceiveQueue, 24 | handlers => handlers 25 | .Add(msg => Console.WriteLine("Handler 1 Received message: {0}", msg.Text)) 26 | .Add(msg => Console.WriteLine("Handler 2 Received message: {0}", msg.Text))); 27 | 28 | this.bus.Receive(AuditQueue, msg => Console.WriteLine("Auditor Received message: {0}", msg.Text)); 29 | 30 | Console.WriteLine("Type a message or 'q' to quit."); 31 | 32 | string text = null; 33 | while ((text = Console.ReadLine()) != "q") 34 | { 35 | foreach (var queue in new[] { SendReceiveQueue, AuditQueue }) 36 | { 37 | this.bus.Send( 38 | queue, 39 | new TestSendMessage 40 | { 41 | Text = text 42 | }); 43 | 44 | this.bus.Send( 45 | queue, 46 | new TestSendMessage2 47 | { 48 | Text = text 49 | }); 50 | } 51 | } 52 | 53 | this.bus.Dispose(); 54 | } 55 | } 56 | 57 | [Serializable] 58 | public class TestSendMessageBase 59 | { 60 | public string Text { get; set; } 61 | } 62 | 63 | [Serializable] 64 | public class TestSendMessage : TestSendMessageBase 65 | { 66 | } 67 | 68 | [Serializable] 69 | public class TestSendMessage2 : TestSendMessageBase 70 | { 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /AzureNetQ/FluentConfiguration/ISubscriptionConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.FluentConfiguration 2 | { 3 | using System.Collections.Generic; 4 | 5 | using Microsoft.ServiceBus.Messaging; 6 | 7 | public interface ISubscriptionConfiguration 8 | { 9 | ISubscriptionConfiguration WithTopic(string topic); 10 | 11 | ISubscriptionConfiguration WithSubscription(string subscription); 12 | 13 | ISubscriptionConfiguration InReadAndDeleteMode(); 14 | 15 | ISubscriptionConfiguration WithDuplicateDetection(); 16 | 17 | ISubscriptionConfiguration WithMaxDeliveryCount(int maxDeliveryCount); 18 | } 19 | 20 | public class SubscriptionConfiguration : ISubscriptionConfiguration 21 | { 22 | public SubscriptionConfiguration() 23 | { 24 | this.Subscription = "Default"; 25 | this.ReceiveMode = ReceiveMode.PeekLock; 26 | this.RequiresDuplicateDetection = false; 27 | this.Topics = new List(); 28 | this.MaxDeliveryCount = 10; 29 | } 30 | 31 | public List Topics { get; private set; } 32 | 33 | public string Subscription { get; private set; } 34 | 35 | public ReceiveMode ReceiveMode { get; private set; } 36 | 37 | public bool RequiresDuplicateDetection { get; set; } 38 | 39 | public int MaxDeliveryCount { get; set; } 40 | 41 | public ISubscriptionConfiguration WithTopic(string topic) 42 | { 43 | this.Topics.Add(topic); 44 | return this; 45 | } 46 | 47 | public ISubscriptionConfiguration WithSubscription(string subscription) 48 | { 49 | this.Subscription = subscription; 50 | return this; 51 | } 52 | 53 | public ISubscriptionConfiguration InReadAndDeleteMode() 54 | { 55 | this.ReceiveMode = ReceiveMode.ReceiveAndDelete; 56 | return this; 57 | } 58 | 59 | public ISubscriptionConfiguration WithDuplicateDetection() 60 | { 61 | this.RequiresDuplicateDetection = true; 62 | return this; 63 | } 64 | 65 | public ISubscriptionConfiguration WithMaxDeliveryCount(int maxDeliveryCount) 66 | { 67 | this.MaxDeliveryCount = maxDeliveryCount; 68 | return this; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /AzureNetQ/JsonSerializer.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System.Text; 4 | 5 | using Newtonsoft.Json; 6 | 7 | public class JsonSerializer : ISerializer 8 | { 9 | private readonly ITypeNameSerializer typeNameSerializer; 10 | 11 | private readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings 12 | { 13 | TypeNameHandling = TypeNameHandling.Auto 14 | }; 15 | 16 | public JsonSerializer(ITypeNameSerializer typeNameSerializer) 17 | { 18 | Preconditions.CheckNotNull(typeNameSerializer, "typeNameSerializer"); 19 | 20 | this.typeNameSerializer = typeNameSerializer; 21 | } 22 | 23 | public byte[] MessageToBytes(T message) where T : class 24 | { 25 | Preconditions.CheckNotNull(message, "message"); 26 | return Encoding.UTF8.GetBytes(this.MessageToString(message)); 27 | } 28 | 29 | public string MessageToString(T message) where T : class 30 | { 31 | Preconditions.CheckNotNull(message, "message"); 32 | return JsonConvert.SerializeObject(message, this.serializerSettings); 33 | } 34 | 35 | public T BytesToMessage(byte[] bytes) 36 | { 37 | Preconditions.CheckNotNull(bytes, "bytes"); 38 | return this.StringToMessage(Encoding.UTF8.GetString(bytes)); 39 | } 40 | 41 | public T StringToMessage(string content) 42 | { 43 | Preconditions.CheckNotNull(content, "content"); 44 | return JsonConvert.DeserializeObject(content, this.serializerSettings); 45 | } 46 | 47 | public object BytesToMessage(string typeName, byte[] bytes) 48 | { 49 | Preconditions.CheckNotNull(typeName, "typeName"); 50 | Preconditions.CheckNotNull(bytes, "bytes"); 51 | 52 | var type = this.typeNameSerializer.DeSerialize(typeName); 53 | 54 | return this.StringToMessage(typeName, Encoding.UTF8.GetString(bytes)); 55 | } 56 | 57 | public object StringToMessage(string typeName, string content) 58 | { 59 | Preconditions.CheckNotNull(typeName, "typeName"); 60 | Preconditions.CheckNotNull(content, "content"); 61 | 62 | var type = this.typeNameSerializer.DeSerialize(typeName); 63 | 64 | return JsonConvert.DeserializeObject(content, type, this.serializerSettings); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /AzureNetQ/AzureNetQException.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | [Serializable] 7 | public class AzureNetQException : Exception 8 | { 9 | public AzureNetQException() 10 | { 11 | } 12 | 13 | public AzureNetQException(string message) 14 | : base(message) 15 | { 16 | } 17 | 18 | public AzureNetQException(string format, params string[] args) 19 | : base(string.Format(format, args)) 20 | { 21 | } 22 | 23 | public AzureNetQException(string message, Exception inner) 24 | : base(message, inner) 25 | { 26 | } 27 | 28 | protected AzureNetQException(SerializationInfo info, StreamingContext context) 29 | : base(info, context) 30 | { 31 | } 32 | } 33 | 34 | [Serializable] 35 | public class AzureNetQInvalidMessageTypeException : AzureNetQException 36 | { 37 | public AzureNetQInvalidMessageTypeException() 38 | { 39 | } 40 | 41 | public AzureNetQInvalidMessageTypeException(string message) 42 | : base(message) 43 | { 44 | } 45 | 46 | public AzureNetQInvalidMessageTypeException(string format, params string[] args) 47 | : base(format, args) 48 | { 49 | } 50 | 51 | public AzureNetQInvalidMessageTypeException(string message, Exception inner) 52 | : base(message, inner) 53 | { 54 | } 55 | 56 | protected AzureNetQInvalidMessageTypeException(SerializationInfo info, StreamingContext context) 57 | : base(info, context) 58 | { 59 | } 60 | } 61 | 62 | [Serializable] 63 | public class AzureNetQResponderException : AzureNetQException 64 | { 65 | public AzureNetQResponderException() 66 | { 67 | } 68 | 69 | public AzureNetQResponderException(string message) 70 | : base(message) 71 | { 72 | } 73 | 74 | public AzureNetQResponderException(string format, params string[] args) 75 | : base(format, args) 76 | { 77 | } 78 | 79 | public AzureNetQResponderException(string message, Exception inner) 80 | : base(message, inner) 81 | { 82 | } 83 | 84 | protected AzureNetQResponderException(SerializationInfo info, StreamingContext context) 85 | : base(info, context) 86 | { 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /AzureNetQ/Conventions.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | 5 | public delegate string ExchangeNameConvention(Type messageType); 6 | 7 | public delegate string TopicNameConvention(Type messageType); 8 | 9 | public delegate string QueueNameConvention(Type messageType); 10 | 11 | public delegate string RpcRoutingKeyNamingConvention(Type messageType); 12 | 13 | public delegate string ErrorQueueNameConvention(); 14 | 15 | public delegate string RpcReturnQueueNamingConvention(); 16 | 17 | public delegate string ConsumerTagConvention(); 18 | 19 | public interface IConventions 20 | { 21 | TopicNameConvention TopicNamingConvention { get; set; } 22 | 23 | QueueNameConvention QueueNamingConvention { get; set; } 24 | 25 | RpcRoutingKeyNamingConvention RpcRoutingKeyNamingConvention { get; set; } 26 | 27 | ErrorQueueNameConvention ErrorQueueNamingConvention { get; set; } 28 | 29 | RpcReturnQueueNamingConvention RpcReturnQueueNamingConvention { get; set; } 30 | 31 | ConsumerTagConvention ConsumerTagConvention { get; set; } 32 | } 33 | 34 | public class Conventions : IConventions 35 | { 36 | public Conventions(ITypeNameSerializer typeNameSerializer) 37 | { 38 | Preconditions.CheckNotNull(typeNameSerializer, "typeNameSerializer"); 39 | 40 | // Establish default conventions. 41 | this.TopicNamingConvention = messageType => string.Empty; 42 | this.RpcRoutingKeyNamingConvention = typeNameSerializer.Serialize; 43 | this.ErrorQueueNamingConvention = () => "AzureNetQ_Default_Error_Queue"; 44 | this.RpcReturnQueueNamingConvention = () => "azurenetq.response." + Guid.NewGuid(); 45 | this.ConsumerTagConvention = () => Guid.NewGuid().ToString(); 46 | this.QueueNamingConvention = messageType => 47 | { 48 | var typeName = typeNameSerializer.Serialize(messageType); 49 | return string.Format("{0}", typeName); 50 | }; 51 | } 52 | 53 | public TopicNameConvention TopicNamingConvention { get; set; } 54 | 55 | public QueueNameConvention QueueNamingConvention { get; set; } 56 | 57 | public RpcRoutingKeyNamingConvention RpcRoutingKeyNamingConvention { get; set; } 58 | 59 | public ErrorQueueNameConvention ErrorQueueNamingConvention { get; set; } 60 | 61 | public RpcReturnQueueNamingConvention RpcReturnQueueNamingConvention { get; set; } 62 | 63 | public ConsumerTagConvention ConsumerTagConvention { get; set; } 64 | } 65 | } -------------------------------------------------------------------------------- /AzureNetQ/NonGeneric/NonGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.NonGeneric 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | 8 | using AzureNetQ.FluentConfiguration; 9 | 10 | public static class NonGenericExtensions 11 | { 12 | public static IDisposable Subscribe(this IBus bus, Type messageType, Action onMessage) 13 | { 14 | return Subscribe(bus, messageType, onMessage, configuration => { }); 15 | } 16 | 17 | public static IDisposable Subscribe( 18 | this IBus bus, 19 | Type messageType, 20 | Action onMessage, 21 | Action configure) 22 | { 23 | Preconditions.CheckNotNull(onMessage, "onMessage"); 24 | 25 | Func asyncOnMessage = x => TaskHelpers.ExecuteSynchronously(() => onMessage(x)); 26 | 27 | return SubscribeAsync(bus, messageType, asyncOnMessage, configure); 28 | } 29 | 30 | public static IDisposable SubscribeAsync(this IBus bus, Type messageType, Func onMessage) 31 | { 32 | return SubscribeAsync(bus, messageType, onMessage, configuration => { }); 33 | } 34 | 35 | public static IDisposable SubscribeAsync( 36 | this IBus bus, 37 | Type messageType, 38 | Func onMessage, 39 | Action configure) 40 | { 41 | Preconditions.CheckNotNull(bus, "bus"); 42 | Preconditions.CheckNotNull(messageType, "messageType"); 43 | Preconditions.CheckNotNull(onMessage, "onMessage"); 44 | Preconditions.CheckNotNull(configure, "configure"); 45 | 46 | var subscribeMethodOpen = 47 | typeof(IBus).GetMethods().SingleOrDefault(x => x.Name == "SubscribeAsync" && HasCorrectParameters(x)); 48 | 49 | if (subscribeMethodOpen == null) 50 | { 51 | throw new AzureNetQException("API change? SubscribeAsync method not found on IBus"); 52 | } 53 | 54 | var subscribeMethod = subscribeMethodOpen.MakeGenericMethod(messageType); 55 | return (IDisposable)subscribeMethod.Invoke(bus, new object[] { onMessage, configure }); 56 | } 57 | 58 | private static bool HasCorrectParameters(MethodInfo methodInfo) 59 | { 60 | var parameters = methodInfo.GetParameters(); 61 | 62 | return 63 | parameters.Length == 2 && 64 | parameters[0].ParameterType.Name == "Func`2" && 65 | parameters[1].ParameterType == typeof(Action); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/LatencyRecorder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | 7 | namespace AzureNetQ.Tests.SimpleRequester 8 | { 9 | public class LatencyRecorder : ILatencyRecorder 10 | { 11 | private readonly IDictionary requests = 12 | new ConcurrentDictionary(); 13 | 14 | private readonly Timer reportTimer; 15 | 16 | private readonly TimeSpan reportInterval; 17 | 18 | public LatencyRecorder() 19 | { 20 | reportInterval = TimeSpan.FromSeconds(10); 21 | reportTimer = new Timer(Report, null, reportInterval, reportInterval); 22 | } 23 | 24 | public void Dispose() 25 | { 26 | reportTimer.Dispose(); 27 | } 28 | 29 | public void RegisterRequest(long requestId) 30 | { 31 | requests.Add(requestId, new RequestRecord(requestId)); 32 | } 33 | 34 | public void RegisterResponse(long responseId) 35 | { 36 | if (!requests.ContainsKey(responseId)) 37 | { 38 | // see if it turns up 39 | Thread.Sleep(100); 40 | if (!requests.ContainsKey(responseId)) 41 | { 42 | Console.WriteLine("Response contains unknown key: {0}", responseId); 43 | return; 44 | } 45 | } 46 | requests[responseId].Respond(); 47 | } 48 | 49 | public void Report(object status) 50 | { 51 | var ticks = DateTime.Now.AddSeconds(-10).Ticks; 52 | var lateResponses = requests.Where(x => (!x.Value.HasResponded) && (x.Value.Ticks < ticks)); 53 | 54 | var reponded = requests.Count(x => x.Value.HasResponded); 55 | 56 | Console.WriteLine("Total: {0}, reponded: {1} over 10 seconds late: [{2}]", 57 | requests.Count, 58 | reponded, 59 | string.Join(",", lateResponses.Select(x => x.Value.Id.ToString()))); 60 | } 61 | } 62 | 63 | public class RequestRecord 64 | { 65 | public RequestRecord(long id) 66 | { 67 | Id = id; 68 | Ticks = DateTime.Now.Ticks; 69 | } 70 | 71 | public void Respond() 72 | { 73 | HasResponded = true; 74 | ResponseTimeTicks = DateTime.Now.Ticks - Ticks; 75 | } 76 | 77 | public long Id { get; private set; } 78 | public long Ticks { get; private set; } 79 | public bool HasResponded { get; private set; } 80 | public long ResponseTimeTicks { get; private set; } 81 | } 82 | } -------------------------------------------------------------------------------- /Packages.dgml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 42 | 43 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.PublishSubscribe/AzureNetQ.Tests.PublishSubscribe.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA} 8 | Exe 9 | Properties 10 | AzureNetQ.Tests.PublishSubscribe 11 | AzureNetQ.Tests.PublishSubscribe 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B} 54 | AzureNetQ 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.Messages/AzureNetQ.Tests.Messages.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FD277901-413F-4064-8A38-57A3609872CB} 8 | Library 9 | Properties 10 | AzureNetQ.Tests.Messages 11 | AzureNetQ.Tests.Messages 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | bin\DebugCloud\ 36 | DEBUG;TRACE 37 | full 38 | AnyCPU 39 | prompt 40 | MinimumRecommendedRules.ruleset 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 63 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SendReceive/AzureNetQ.Tests.SendReceive.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8} 8 | Exe 9 | Properties 10 | AzureNetQ.Tests.SendReceive 11 | AzureNetQ.Tests.SendReceive 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {fd277901-413f-4064-8a38-57a3609872cb} 53 | AzureNetQ.Tests.Messages 54 | 55 | 56 | {b8def709-5168-48f1-b8d3-ad44e4a4a22b} 57 | AzureNetQ 58 | 59 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /AzureNetQ/Consumer/HandlerCollection.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Consumer 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | public class HandlerCollection : IHandlerCollection 9 | { 10 | private readonly IDictionary handlers = new Dictionary(); 11 | 12 | private readonly IAzureNetQLogger logger; 13 | 14 | public HandlerCollection(IAzureNetQLogger logger) 15 | { 16 | Preconditions.CheckNotNull(logger, "logger"); 17 | 18 | this.logger = logger; 19 | this.ThrowOnNoMatchingHandler = true; 20 | } 21 | 22 | public bool ThrowOnNoMatchingHandler { get; set; } 23 | 24 | public IHandlerRegistration Add(Func handler) where T : class 25 | { 26 | Preconditions.CheckNotNull(handler, "handler"); 27 | 28 | if (this.handlers.ContainsKey(typeof(T))) 29 | { 30 | throw new AzureNetQException("There is already a handler for message type '{0}'", typeof(T).Name); 31 | } 32 | 33 | this.handlers.Add(typeof(T), handler); 34 | return this; 35 | } 36 | 37 | public IHandlerRegistration Add(Action handler) where T : class 38 | { 39 | Preconditions.CheckNotNull(handler, "handler"); 40 | 41 | this.Add(message => TaskHelpers.ExecuteSynchronously(() => handler(message))); 42 | return this; 43 | } 44 | 45 | // NOTE: refactoring tools might suggest this method is never invoked. Ignore them it 46 | // _is_ invoked by the GetHandler(Type messsageType) method below by reflection. 47 | public Func GetHandler() where T : class 48 | { 49 | // return (Func, MessageReceivedInfo, Task>)GetHandler(typeof(T)); 50 | var messageType = typeof(T); 51 | 52 | if (this.handlers.ContainsKey(messageType)) 53 | { 54 | return (Func)this.handlers[messageType]; 55 | } 56 | 57 | // no exact handler match found, so let's see if we can find a handler that 58 | // handles a supertype of the consumed message. 59 | foreach (var handlerType in this.handlers.Keys.Where(type => type.IsAssignableFrom(messageType))) 60 | { 61 | return (Func)this.handlers[handlerType]; 62 | } 63 | 64 | if (this.ThrowOnNoMatchingHandler) 65 | { 66 | this.logger.ErrorWrite("No handler found for message type {0}", messageType.Name); 67 | throw new AzureNetQException("No handler found for message type {0}", messageType.Name); 68 | } 69 | 70 | return message => Task.Factory.StartNew(() => { }); 71 | } 72 | 73 | public dynamic GetHandler(Type messageType) 74 | { 75 | Preconditions.CheckNotNull(messageType, "messageType"); 76 | 77 | var getHandlerGenericMethod = GetType().GetMethod("GetHandler", new Type[0]).MakeGenericMethod(messageType); 78 | return getHandlerGenericMethod.Invoke(this, new object[0]); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/AzureNetQ.Tests.SimpleRequester.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA} 9 | Exe 10 | Properties 11 | AzureNetQ.Tests.SimpleRequester 12 | AzureNetQ.Tests.SimpleRequester 13 | v4.0 14 | 15 | 16 | 512 17 | 18 | 19 | true 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | full 23 | AnyCPU 24 | prompt 25 | MinimumRecommendedRules.ruleset 26 | 27 | 28 | bin\Release\ 29 | TRACE 30 | true 31 | pdbonly 32 | AnyCPU 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | 36 | 37 | true 38 | bin\DebugCloud\ 39 | DEBUG;TRACE 40 | full 41 | AnyCPU 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {fd277901-413f-4064-8a38-57a3609872cb} 59 | AzureNetQ.Tests.Messages 60 | 61 | 62 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B} 63 | AzureNetQ 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleService/AzureNetQ.Tests.SimpleService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3} 9 | Exe 10 | Properties 11 | AzureNetQ.Tests.SimpleService 12 | AzureNetQ.Tests.SimpleService 13 | v4.0 14 | 15 | 16 | 512 17 | 18 | 19 | true 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | full 23 | AnyCPU 24 | prompt 25 | MinimumRecommendedRules.ruleset 26 | 27 | 28 | bin\Release\ 29 | TRACE 30 | true 31 | pdbonly 32 | AnyCPU 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | 36 | 37 | true 38 | bin\DebugCloud\ 39 | DEBUG;TRACE 40 | full 41 | AnyCPU 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Properties\Version.cs 52 | 53 | 54 | 55 | 56 | 57 | 58 | {fd277901-413f-4064-8a38-57a3609872cb} 59 | AzureNetQ.Tests.Messages 60 | 61 | 62 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B} 63 | AzureNetQ 64 | 65 | 66 | 67 | 68 | Designer 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /AzureNetQ/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AzureNetQ/IBus.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | using AzureNetQ.Consumer; 7 | using AzureNetQ.FluentConfiguration; 8 | 9 | /// 10 | /// Provides a simple Publish/Subscribe and Request/Response API for a message bus. 11 | /// 12 | public interface IBus : IDisposable 13 | { 14 | IAzureNetQLogger Logger { get; } 15 | 16 | IConventions Conventions { get; } 17 | 18 | void Publish(T message) where T : class; 19 | 20 | void Publish(T message, string topic) where T : class; 21 | 22 | void Publish(T message, Action configure) where T : class; 23 | 24 | void Publish(T message, string topic, Action configure) where T : class; 25 | 26 | void Publish(Type type, object message); 27 | 28 | void Publish(Type type, object message, string topic); 29 | 30 | void Publish(Type type, object message, Action configure); 31 | 32 | void Publish(Type type, object message, string topic, Action configure); 33 | 34 | Task PublishAsync(T message) where T : class; 35 | 36 | Task PublishAsync(T message, string topic) where T : class; 37 | 38 | Task PublishAsync(T message, Action configure) where T : class; 39 | 40 | Task PublishAsync(T message, string topic, Action configure) where T : class; 41 | 42 | Task PublishAsync(Type type, object message); 43 | 44 | Task PublishAsync(Type type, object message, string topic); 45 | 46 | Task PublishAsync(Type type, object message, Action configure); 47 | 48 | Task PublishAsync(Type type, object message, string topicName, Action configure); 49 | 50 | void Subscribe(Action onMessage) where T : class; 51 | 52 | void Subscribe(Action onMessage, Action configure) where T : class; 53 | 54 | void SubscribeAsync(Func onMessage) where T : class; 55 | 56 | void SubscribeAsync(Func onMessage, Action configure) where T : class; 57 | 58 | TResponse Request(TRequest request) 59 | where TRequest : class 60 | where TResponse : class; 61 | 62 | TResponse Request(TRequest request, Action configure) 63 | where TRequest : class 64 | where TResponse : class; 65 | 66 | Task RequestAsync(TRequest request) 67 | where TRequest : class 68 | where TResponse : class; 69 | 70 | Task RequestAsync(TRequest request, Action configure) 71 | where TRequest : class 72 | where TResponse : class; 73 | 74 | void Respond(Func responder) 75 | where TRequest : class 76 | where TResponse : class; 77 | 78 | void Respond(Func responder, Action configure) 79 | where TRequest : class 80 | where TResponse : class; 81 | 82 | void RespondAsync(Func> responder) 83 | where TRequest : class 84 | where TResponse : class; 85 | 86 | void RespondAsync(Func> responder, Action configure) 87 | where TRequest : class 88 | where TResponse : class; 89 | 90 | void Send(string queue, T message) 91 | where T : class; 92 | 93 | IDisposable Receive(string queue, Action onMessage) 94 | where T : class; 95 | 96 | IDisposable Receive(string queue, Func onMessage) 97 | where T : class; 98 | 99 | IDisposable Receive(string queue, Action addHandlers); 100 | } 101 | } -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/Program.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Tests.SimpleRequester 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | using AzureNetQ.Loggers; 7 | using AzureNetQ.Tests.Messages; 8 | 9 | public class Program 10 | { 11 | private const int PublishIntervalMilliseconds = 20; 12 | 13 | private static readonly object RequestLock = new object(); 14 | 15 | private static readonly IBus Bus = 16 | AzureBusFactory.CreateBus( 17 | new AzureNetQSettings 18 | { 19 | Logger = () => new NoDebugLogger(), 20 | ConnectionConfiguration = new ConnectionConfiguration 21 | { 22 | PrefetchCount = 200, 23 | MaxConcurrentCalls = 100, 24 | BatchingInterval = TimeSpan.FromMilliseconds(50) 25 | } 26 | }); 27 | 28 | private static readonly ILatencyRecorder LatencyRecorder = new LatencyRecorder(); 29 | 30 | private static long count; 31 | 32 | public static void Main(string[] args) 33 | { 34 | var timer = new Timer(OnTimer, null, PublishIntervalMilliseconds, PublishIntervalMilliseconds); 35 | 36 | Console.Out.WriteLine("Timer running, ctrl-C to end"); 37 | 38 | Console.CancelKeyPress += (source, cancelKeyPressArgs) => 39 | { 40 | Console.Out.WriteLine("Shutting down"); 41 | 42 | timer.Dispose(); 43 | Bus.Dispose(); 44 | LatencyRecorder.Dispose(); 45 | 46 | Console.WriteLine("Shut down complete"); 47 | }; 48 | 49 | Thread.Sleep(Timeout.Infinite); 50 | } 51 | 52 | public static void OnTimer(object state) 53 | { 54 | try 55 | { 56 | lock (RequestLock) 57 | { 58 | Console.WriteLine("Sending {0}", count); 59 | Bus.RequestAsync( 60 | new TestAsyncRequestMessage 61 | { 62 | Id = count, 63 | Text = string.Format("Hello from client number: {0}! ", count) 64 | }).ContinueWith( 65 | t => 66 | { 67 | if (t.IsFaulted && t.Exception != null) 68 | { 69 | foreach (var exception in t.Exception.InnerExceptions) 70 | { 71 | Console.WriteLine("Exception thrown by Response: {0}", exception.Message); 72 | } 73 | 74 | return; 75 | } 76 | 77 | ResponseHandler(t.Result); 78 | }); 79 | 80 | LatencyRecorder.RegisterRequest(count); 81 | count++; 82 | } 83 | } 84 | catch (Exception exception) 85 | { 86 | Console.WriteLine("Exception thrown by Publish: {0}", exception.Message); 87 | } 88 | } 89 | 90 | public static void ResponseHandler(TestAsyncResponseMessage response) 91 | { 92 | Console.WriteLine("Response: {0}", response.Text); 93 | LatencyRecorder.RegisterResponse(response.Id); 94 | } 95 | } 96 | 97 | public class NoDebugLogger : IAzureNetQLogger 98 | { 99 | private readonly ConsoleLogger consoleLogger = new ConsoleLogger(); 100 | 101 | public void DebugWrite(string format, params object[] args) 102 | { 103 | // do nothing 104 | } 105 | 106 | public void InfoWrite(string format, params object[] args) 107 | { 108 | // do nothing 109 | } 110 | 111 | public void ErrorWrite(string format, params object[] args) 112 | { 113 | this.consoleLogger.ErrorWrite(format, args); 114 | } 115 | 116 | public void ErrorWrite(Exception exception) 117 | { 118 | this.consoleLogger.ErrorWrite(exception); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /AzureNetQ/Producer/SendReceive.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Producer 2 | { 3 | using System; 4 | using System.Collections.Concurrent; 5 | using System.Threading.Tasks; 6 | 7 | using AzureNetQ.Consumer; 8 | 9 | using Microsoft.ServiceBus.Messaging; 10 | 11 | public class SendReceive : ISendReceive 12 | { 13 | private readonly IAzureAdvancedBus advancedBus; 14 | 15 | private readonly IHandlerCollectionFactory handlerCollectionFactory; 16 | 17 | private readonly ITypeNameSerializer typeNameSerializer; 18 | 19 | private readonly ISerializer serializer; 20 | 21 | private readonly ConcurrentDictionary declaredQueues = new ConcurrentDictionary(); 22 | 23 | public SendReceive( 24 | IAzureAdvancedBus advancedBus, 25 | IConnectionConfiguration connectionConfiguration, 26 | IHandlerCollectionFactory handlerCollectionFactory, 27 | ITypeNameSerializer typeNameSerializer, 28 | ISerializer serializer) 29 | { 30 | Preconditions.CheckNotNull(advancedBus, "advancedBus"); 31 | Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration"); 32 | Preconditions.CheckNotNull(handlerCollectionFactory, "handlerCollectionFactory"); 33 | Preconditions.CheckNotNull(typeNameSerializer, "typeNameSerializer"); 34 | Preconditions.CheckNotNull(serializer, "serializer"); 35 | 36 | this.advancedBus = advancedBus; 37 | this.handlerCollectionFactory = handlerCollectionFactory; 38 | this.typeNameSerializer = typeNameSerializer; 39 | this.serializer = serializer; 40 | } 41 | 42 | public void Send(string queue, T message) 43 | where T : class 44 | { 45 | Preconditions.CheckNotNull(queue, "queue"); 46 | Preconditions.CheckNotNull(message, "message"); 47 | 48 | var declaredQueue = this.DeclareQueue(queue); 49 | 50 | var content = this.serializer.MessageToString(message); 51 | var queueMessage = new BrokeredMessage(content); 52 | queueMessage.SetMessageType(this.typeNameSerializer.Serialize(typeof(T))); 53 | 54 | declaredQueue.Send(queueMessage); 55 | } 56 | 57 | public IDisposable Receive(string queue, Action onMessage) 58 | where T : class 59 | { 60 | Preconditions.CheckNotNull(queue, "queue"); 61 | Preconditions.CheckNotNull(onMessage, "onMessage"); 62 | 63 | return this.Receive(queue, message => TaskHelpers.ExecuteSynchronously(() => onMessage(message))); 64 | } 65 | 66 | public IDisposable Receive(string queue, Func onMessage) 67 | where T : class 68 | { 69 | Preconditions.CheckNotNull(queue, "queue"); 70 | Preconditions.CheckNotNull(onMessage, "onMessage"); 71 | 72 | var declaredQueue = this.DeclareQueue(queue); 73 | return this.Consume(declaredQueue, handlers => handlers.Add(onMessage)); 74 | } 75 | 76 | public IDisposable Receive(string queue, Action addHandlers) 77 | { 78 | Preconditions.CheckNotNull(queue, "queue"); 79 | Preconditions.CheckNotNull(addHandlers, "addHandlers"); 80 | 81 | var declaredQueue = this.DeclareQueue(queue); 82 | return this.Consume(declaredQueue, x => addHandlers(new HandlerAdder(x))); 83 | } 84 | 85 | private IDisposable Consume(QueueClient declaredQueue, Action addHandlers) 86 | { 87 | var handlerCollection = this.handlerCollectionFactory.CreateHandlerCollection(); 88 | addHandlers(handlerCollection); 89 | 90 | declaredQueue.OnMessageAsync(queueMessage => 91 | { 92 | var messageBody = queueMessage.GetBody(); 93 | var messageType = queueMessage.GetMessageType(); 94 | 95 | var message = this.serializer.StringToMessage(messageType, messageBody); 96 | var handler = handlerCollection.GetHandler(message.GetType()); 97 | 98 | return handler((dynamic)message); 99 | }); 100 | 101 | return null; 102 | } 103 | 104 | private QueueClient DeclareQueue(string queueName) 105 | { 106 | QueueClient queue = null; 107 | this.declaredQueues.AddOrUpdate( 108 | queueName, 109 | key => queue = this.advancedBus.QueueDeclare(queueName), 110 | (key, value) => queue = value); 111 | 112 | return queue; 113 | } 114 | 115 | private class HandlerAdder : IReceiveRegistration 116 | { 117 | private readonly IHandlerRegistration handlerRegistration; 118 | 119 | public HandlerAdder(IHandlerRegistration handlerRegistration) 120 | { 121 | this.handlerRegistration = handlerRegistration; 122 | } 123 | 124 | public IReceiveRegistration Add(Func onMessage) where T : class 125 | { 126 | this.handlerRegistration.Add(onMessage); 127 | return this; 128 | } 129 | 130 | public IReceiveRegistration Add(Action onMessage) where T : class 131 | { 132 | this.handlerRegistration.Add(onMessage); 133 | return this; 134 | } 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleService/Program.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ.Tests.SimpleService 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | using AzureNetQ.Loggers; 9 | using AzureNetQ.Tests.Messages; 10 | 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | var bus = 16 | AzureBusFactory.CreateBus( 17 | new AzureNetQSettings 18 | { 19 | Logger = () => new NoDebugLogger(), 20 | ConnectionConfiguration = new ConnectionConfiguration 21 | { 22 | PrefetchCount = 200, 23 | MaxConcurrentCalls = 100, 24 | BatchingInterval = TimeSpan.FromMilliseconds(50) 25 | } 26 | }); 27 | 28 | bus.RespondAsync(HandleAsyncRequest); 29 | 30 | Console.WriteLine("Waiting to service requests"); 31 | Console.WriteLine("Ctrl-C to exit"); 32 | 33 | Console.CancelKeyPress += (source, cancelKeyPressArgs) => 34 | { 35 | bus.Dispose(); 36 | Console.WriteLine("Shut down complete"); 37 | }; 38 | 39 | Thread.Sleep(Timeout.Infinite); 40 | } 41 | 42 | public static TestResponseMessage HandleRequest(TestRequestMessage request) 43 | { 44 | Console.WriteLine("Handling request: {0}", request.Text); 45 | if (request.CausesServerToTakeALongTimeToRespond) 46 | { 47 | Console.Out.WriteLine("Taking a long time to respond..."); 48 | Thread.Sleep(5000); 49 | Console.Out.WriteLine("... responding"); 50 | } 51 | 52 | if (request.CausesExceptionInServer) 53 | { 54 | if (request.ExceptionInServerMessage != null) 55 | { 56 | throw new SomeRandomException(request.ExceptionInServerMessage); 57 | } 58 | 59 | throw new SomeRandomException("Something terrible has just happened!"); 60 | } 61 | 62 | return new TestResponseMessage { Id = request.Id, Text = request.Text + " all done!" }; 63 | } 64 | 65 | private static Task HandleAsyncRequest(TestAsyncRequestMessage request) 66 | { 67 | Console.WriteLine("Handling request: {0}", request.Text); 68 | 69 | var tcs = new TaskCompletionSource(); 70 | tcs.SetResult(new TestAsyncResponseMessage { Id = request.Id, Text = request.Text + " ... completed." }); 71 | 72 | return tcs.Task; 73 | } 74 | 75 | private static Task RunDelayed(int millisecondsDelay, Func func) 76 | { 77 | if (func == null) 78 | { 79 | throw new ArgumentNullException("func"); 80 | } 81 | 82 | if (millisecondsDelay < 0) 83 | { 84 | throw new ArgumentOutOfRangeException("millisecondsDelay"); 85 | } 86 | 87 | var taskCompletionSource = new TaskCompletionSource(); 88 | 89 | var timer = new Timer(self => 90 | { 91 | ((Timer)self).Dispose(); 92 | try 93 | { 94 | var result = func(); 95 | taskCompletionSource.SetResult(result); 96 | } 97 | catch (Exception exception) 98 | { 99 | taskCompletionSource.SetException(exception); 100 | } 101 | }); 102 | timer.Change(millisecondsDelay, millisecondsDelay); 103 | 104 | return taskCompletionSource.Task; 105 | } 106 | } 107 | 108 | [Serializable] 109 | public class SomeRandomException : Exception 110 | { 111 | //// For guidelines regarding the creation of new exception types, see 112 | //// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp 113 | //// and 114 | //// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp 115 | 116 | public SomeRandomException() 117 | { 118 | } 119 | 120 | public SomeRandomException(string message) 121 | : base(message) 122 | { 123 | } 124 | 125 | public SomeRandomException(string message, Exception inner) 126 | : base(message, inner) 127 | { 128 | } 129 | 130 | protected SomeRandomException(SerializationInfo info, StreamingContext context) 131 | : base(info, context) 132 | { 133 | } 134 | } 135 | 136 | public class NoDebugLogger : IAzureNetQLogger 137 | { 138 | private readonly ConsoleLogger logger = new ConsoleLogger(); 139 | 140 | public void DebugWrite(string format, params object[] args) 141 | { 142 | } 143 | 144 | public void InfoWrite(string format, params object[] args) 145 | { 146 | } 147 | 148 | public void ErrorWrite(string format, params object[] args) 149 | { 150 | this.logger.ErrorWrite(format, args); 151 | } 152 | 153 | public void ErrorWrite(Exception exception) 154 | { 155 | this.logger.ErrorWrite(exception); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /AzureNetQ.Tests/AzureNetQ.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {640DEC15-3A17-4E85-B38A-CFB379426DC2} 9 | Library 10 | Properties 11 | AzureNetQ.Tests 12 | AzureNetQ.Tests 13 | v4.0 14 | 512 15 | 16 | 17 | 18 | 19 | 20 | 3.5 21 | publish\ 22 | true 23 | Disk 24 | false 25 | Foreground 26 | 7 27 | Days 28 | false 29 | false 30 | true 31 | 0 32 | 1.0.0.%2a 33 | false 34 | false 35 | true 36 | ..\ 37 | true 38 | 39 | 40 | true 41 | full 42 | false 43 | bin\Debug\ 44 | DEBUG;TRACE 45 | prompt 46 | 4 47 | AllRules.ruleset 48 | 49 | 50 | pdbonly 51 | true 52 | bin\Release\ 53 | TRACE 54 | prompt 55 | 4 56 | AllRules.ruleset 57 | 58 | 59 | true 60 | bin\DebugCloud\ 61 | DEBUG;TRACE 62 | full 63 | AnyCPU 64 | prompt 65 | AllRules.ruleset 66 | 67 | 68 | 69 | 70 | ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll 71 | 72 | 73 | ..\packages\NUnit.2.6.2\lib\nunit.framework.dll 74 | 75 | 76 | False 77 | ..\packages\RabbitMQ.Client.3.2.1\lib\net30\RabbitMQ.Client.dll 78 | 79 | 80 | ..\packages\RhinoMocks.3.6.1\lib\net\Rhino.Mocks.dll 81 | 82 | 83 | 84 | 85 | 86 | 87 | Properties\Version.cs 88 | 89 | 90 | 91 | 92 | 93 | {9888950b-ef30-4763-9076-38b071cdb535} 94 | AzureNetQ.Management.Client 95 | 96 | 97 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B} 98 | AzureNetQ 99 | 100 | 101 | 102 | 103 | False 104 | .NET Framework 3.5 SP1 Client Profile 105 | false 106 | 107 | 108 | False 109 | .NET Framework 3.5 SP1 110 | true 111 | 112 | 113 | False 114 | Windows Installer 3.1 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 131 | -------------------------------------------------------------------------------- /AzureNetQ/AzureNetQ.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B} 9 | Library 10 | Properties 11 | AzureNetQ 12 | AzureNetQ 13 | v4.0 14 | 512 15 | 16 | 17 | ..\ 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | bin\Release\AzureNetQ.xml 38 | false 39 | 40 | 41 | bin\Staging\ 42 | TRACE 43 | bin\Release\AzureNetQ.xml 44 | true 45 | pdbonly 46 | AnyCPU 47 | prompt 48 | MinimumRecommendedRules.ruleset 49 | false 50 | 51 | 52 | 53 | 54 | ..\packages\ServiceBus.v1_1.1.0.3.0\lib\net40-full\Microsoft.ServiceBus.dll 55 | 56 | 57 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.2.0.0.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll 58 | 59 | 60 | False 61 | ..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 137 | -------------------------------------------------------------------------------- /AzureNetQ/Preconditions.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | /// 8 | /// Collection of precondition methods for qualifying method arguments. 9 | /// 10 | internal static class Preconditions 11 | { 12 | /// 13 | /// Ensures that is not null. 14 | /// 15 | /// 16 | /// The value to check, must not be null. 17 | /// 18 | /// 19 | /// The name of the parameter the value is taken from, must not be 20 | /// blank. 21 | /// 22 | /// 23 | /// Thrown if is null. 24 | /// 25 | /// 26 | /// Thrown if is blank. 27 | /// 28 | public static void CheckNotNull(T value, string name) where T : class 29 | { 30 | CheckNotNull(value, name, string.Format("{0} must not be null", name)); 31 | } 32 | 33 | /// 34 | /// Ensures that is not null. 35 | /// 36 | /// 37 | /// The value to check, must not be null. 38 | /// 39 | /// 40 | /// The name of the parameter the value is taken from, must not be 41 | /// blank. 42 | /// 43 | /// 44 | /// The message to provide to the exception if 45 | /// is null, must not be blank. 46 | /// 47 | /// 48 | /// Thrown if is null. 49 | /// 50 | /// 51 | /// Thrown if or are 52 | /// blank. 53 | /// 54 | public static void CheckNotNull(T value, string name, string message) where T : class 55 | { 56 | CheckNotBlank(name, "name", "name must not be blank"); 57 | CheckNotBlank(message, "message", "message must not be blank"); 58 | 59 | if (value == null) 60 | { 61 | throw new ArgumentNullException(name, message); 62 | } 63 | } 64 | 65 | /// 66 | /// Ensures that is not blank. 67 | /// 68 | /// 69 | /// The value to check, must not be blank. 70 | /// 71 | /// 72 | /// The name of the parameter the value is taken from, must not be 73 | /// blank. 74 | /// 75 | /// 76 | /// The message to provide to the exception if 77 | /// is blank, must not be blank. 78 | /// 79 | /// 80 | /// Thrown if , , or 81 | /// are blank. 82 | /// 83 | public static void CheckNotBlank(string value, string name, string message) 84 | { 85 | if (string.IsNullOrWhiteSpace(name)) 86 | { 87 | throw new ArgumentException("name must not be blank", "name"); 88 | } 89 | 90 | if (string.IsNullOrWhiteSpace(message)) 91 | { 92 | throw new ArgumentException("message must not be blank", "message"); 93 | } 94 | 95 | if (string.IsNullOrWhiteSpace(value)) 96 | { 97 | throw new ArgumentException(message, name); 98 | } 99 | } 100 | 101 | /// 102 | /// Ensures that is not blank. 103 | /// 104 | /// 105 | /// The value to check, must not be blank. 106 | /// 107 | /// 108 | /// The name of the parameter the value is taken from, must not be 109 | /// blank. 110 | /// 111 | /// 112 | /// Thrown if or are 113 | /// blank. 114 | /// 115 | public static void CheckNotBlank(string value, string name) 116 | { 117 | CheckNotBlank(value, name, string.Format("{0} must not be blank", name)); 118 | } 119 | 120 | /// 121 | /// Ensures that contains at least one 122 | /// item. 123 | /// 124 | /// 125 | /// The collection to check, must not be null or empty. 126 | /// 127 | /// 128 | /// The name of the parameter the collection is taken from, must not be 129 | /// blank. 130 | /// 131 | /// 132 | /// The message to provide to the exception if 133 | /// is empty, must not be blank. 134 | /// 135 | /// 136 | /// Thrown if is empty, or if 137 | /// or are blank. 138 | /// 139 | public static void CheckAny(IEnumerable collection, string name, string message) 140 | { 141 | CheckNotBlank(name, "name", "name must not be blank"); 142 | CheckNotBlank(message, "message", "message must not be blank"); 143 | 144 | if (collection == null || !collection.Any()) 145 | { 146 | throw new ArgumentException(message, name); 147 | } 148 | } 149 | 150 | /// 151 | /// Ensures that is true. 152 | /// 153 | /// 154 | /// The value to check, must be true. 155 | /// 156 | /// 157 | /// The name of the parameter the value is taken from, must not be 158 | /// blank. 159 | /// 160 | /// 161 | /// The message to provide to the exception if 162 | /// is false, must not be blank. 163 | /// 164 | /// 165 | /// Thrown if is false, or if 166 | /// or are blank. 167 | /// 168 | public static void CheckTrue(bool value, string name, string message) 169 | { 170 | CheckNotBlank(name, "name", "name must not be blank"); 171 | CheckNotBlank(message, "message", "message must not be blank"); 172 | 173 | if (!value) 174 | { 175 | throw new ArgumentException(message, name); 176 | } 177 | } 178 | 179 | /// 180 | /// Ensures that is false. 181 | /// 182 | /// 183 | /// The value to check, must be false. 184 | /// 185 | /// 186 | /// The name of the parameter the value is taken from, must not be 187 | /// blank. 188 | /// 189 | /// 190 | /// The message to provide to the exception if 191 | /// is true, must not be blank. 192 | /// 193 | /// 194 | /// Thrown if is true, or if 195 | /// or are blank. 196 | /// 197 | public static void CheckFalse(bool value, string name, string message) 198 | { 199 | CheckNotBlank(name, "name", "name must not be blank"); 200 | CheckNotBlank(message, "message", "message must not be blank"); 201 | 202 | if (value) 203 | { 204 | throw new ArgumentException(message, name); 205 | } 206 | } 207 | 208 | public static void CheckShortString(string value, string name) 209 | { 210 | CheckNotNull(value, name); 211 | if (value.Length > 255) 212 | { 213 | throw new ArgumentException(string.Format("Argument '{0}' must be less than or equal to 255 characters.", name)); 214 | } 215 | } 216 | 217 | public static void CheckTypeMatches(Type expectedType, object value, string name, string message) 218 | { 219 | CheckNotBlank(name, "name", "name must not be blank"); 220 | CheckNotBlank(message, "message", "message must not be blank"); 221 | if (!expectedType.IsAssignableFrom(value.GetType())) 222 | { 223 | throw new ArgumentException(message, name); 224 | } 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SendReceive/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | False 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleRequester/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | False 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.SimpleService/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | False 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /AzureNetQ.Tests.PublishSubscribe/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | False 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /AzureNetQ/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | False 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | False 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /AzureNetQ.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ", "AzureNetQ\AzureNetQ.csproj", "{B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests", "AzureNetQ.Tests\AzureNetQ.Tests.csproj", "{640DEC15-3A17-4E85-B38A-CFB379426DC2}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests.SimpleService", "AzureNetQ.Tests.SimpleService\AzureNetQ.Tests.SimpleService.csproj", "{D5166633-83A2-48FA-B534-C2EC9D9DE9C3}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests.SimpleRequester", "AzureNetQ.Tests.SimpleRequester\AzureNetQ.Tests.SimpleRequester.csproj", "{5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests.Messages", "AzureNetQ.Tests.Messages\AzureNetQ.Tests.Messages.csproj", "{FD277901-413F-4064-8A38-57A3609872CB}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests.SendReceive", "AzureNetQ.Tests.SendReceive\AzureNetQ.Tests.SendReceive.csproj", "{4818FCD2-1E75-4CEA-8B00-E5259E217BB8}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureNetQ.Tests.PublishSubscribe", "AzureNetQ.Tests.PublishSubscribe\AzureNetQ.Tests.PublishSubscribe.csproj", "{6D68DFA2-6271-4847-96FA-631AE49D2CCA}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Debug|Mixed Platforms = Debug|Mixed Platforms 24 | Debug|x86 = Debug|x86 25 | DebugCloud|Any CPU = DebugCloud|Any CPU 26 | DebugCloud|Mixed Platforms = DebugCloud|Mixed Platforms 27 | DebugCloud|x86 = DebugCloud|x86 28 | Release|Any CPU = Release|Any CPU 29 | Release|Mixed Platforms = Release|Mixed Platforms 30 | Release|x86 = Release|x86 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 36 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 37 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Debug|x86.ActiveCfg = Debug|Any CPU 38 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.DebugCloud|Any CPU.ActiveCfg = Debug|Any CPU 39 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.DebugCloud|Any CPU.Build.0 = Debug|Any CPU 40 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 41 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 42 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.DebugCloud|x86.ActiveCfg = Debug|Any CPU 43 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 46 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Release|Mixed Platforms.Build.0 = Release|Any CPU 47 | {B8DEF709-5168-48F1-B8D3-AD44E4A4A22B}.Release|x86.ActiveCfg = Release|Any CPU 48 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 51 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 52 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Debug|x86.ActiveCfg = Debug|Any CPU 53 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.DebugCloud|Any CPU.ActiveCfg = DebugCloud|Any CPU 54 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.DebugCloud|Any CPU.Build.0 = DebugCloud|Any CPU 55 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 56 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 57 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.DebugCloud|x86.ActiveCfg = DebugCloud|Any CPU 58 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 61 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Release|Mixed Platforms.Build.0 = Release|Any CPU 62 | {640DEC15-3A17-4E85-B38A-CFB379426DC2}.Release|x86.ActiveCfg = Release|Any CPU 63 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 66 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 67 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Debug|x86.ActiveCfg = Debug|Any CPU 68 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.DebugCloud|Any CPU.ActiveCfg = DebugCloud|Any CPU 69 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.DebugCloud|Any CPU.Build.0 = DebugCloud|Any CPU 70 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 71 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 72 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.DebugCloud|x86.ActiveCfg = DebugCloud|Any CPU 73 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 74 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Release|Any CPU.Build.0 = Release|Any CPU 75 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 76 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU 77 | {D5166633-83A2-48FA-B534-C2EC9D9DE9C3}.Release|x86.ActiveCfg = Release|Any CPU 78 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 81 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 82 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Debug|x86.ActiveCfg = Debug|Any CPU 83 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.DebugCloud|Any CPU.ActiveCfg = DebugCloud|Any CPU 84 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.DebugCloud|Any CPU.Build.0 = DebugCloud|Any CPU 85 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 86 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 87 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.DebugCloud|x86.ActiveCfg = DebugCloud|Any CPU 88 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 91 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Release|Mixed Platforms.Build.0 = Release|Any CPU 92 | {5EDAA7BF-CD00-440C-9697-D24F7B37CFFA}.Release|x86.ActiveCfg = Release|Any CPU 93 | {FD277901-413F-4064-8A38-57A3609872CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 94 | {FD277901-413F-4064-8A38-57A3609872CB}.Debug|Any CPU.Build.0 = Debug|Any CPU 95 | {FD277901-413F-4064-8A38-57A3609872CB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 96 | {FD277901-413F-4064-8A38-57A3609872CB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 97 | {FD277901-413F-4064-8A38-57A3609872CB}.Debug|x86.ActiveCfg = Debug|Any CPU 98 | {FD277901-413F-4064-8A38-57A3609872CB}.DebugCloud|Any CPU.ActiveCfg = DebugCloud|Any CPU 99 | {FD277901-413F-4064-8A38-57A3609872CB}.DebugCloud|Any CPU.Build.0 = DebugCloud|Any CPU 100 | {FD277901-413F-4064-8A38-57A3609872CB}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 101 | {FD277901-413F-4064-8A38-57A3609872CB}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 102 | {FD277901-413F-4064-8A38-57A3609872CB}.DebugCloud|x86.ActiveCfg = DebugCloud|Any CPU 103 | {FD277901-413F-4064-8A38-57A3609872CB}.Release|Any CPU.ActiveCfg = Release|Any CPU 104 | {FD277901-413F-4064-8A38-57A3609872CB}.Release|Any CPU.Build.0 = Release|Any CPU 105 | {FD277901-413F-4064-8A38-57A3609872CB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 106 | {FD277901-413F-4064-8A38-57A3609872CB}.Release|Mixed Platforms.Build.0 = Release|Any CPU 107 | {FD277901-413F-4064-8A38-57A3609872CB}.Release|x86.ActiveCfg = Release|Any CPU 108 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 109 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Debug|Any CPU.Build.0 = Debug|Any CPU 110 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 111 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 112 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Debug|x86.ActiveCfg = Debug|Any CPU 113 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.DebugCloud|Any CPU.ActiveCfg = Debug|Any CPU 114 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.DebugCloud|Any CPU.Build.0 = Debug|Any CPU 115 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 116 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 117 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.DebugCloud|x86.ActiveCfg = Debug|Any CPU 118 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Release|Any CPU.ActiveCfg = Release|Any CPU 119 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Release|Any CPU.Build.0 = Release|Any CPU 120 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 121 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Release|Mixed Platforms.Build.0 = Release|Any CPU 122 | {4818FCD2-1E75-4CEA-8B00-E5259E217BB8}.Release|x86.ActiveCfg = Release|Any CPU 123 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 124 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Debug|Any CPU.Build.0 = Debug|Any CPU 125 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 126 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 127 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Debug|x86.ActiveCfg = Debug|Any CPU 128 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.DebugCloud|Any CPU.ActiveCfg = Debug|Any CPU 129 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.DebugCloud|Any CPU.Build.0 = Debug|Any CPU 130 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.DebugCloud|Mixed Platforms.ActiveCfg = Debug|Any CPU 131 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.DebugCloud|Mixed Platforms.Build.0 = Debug|Any CPU 132 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.DebugCloud|x86.ActiveCfg = Debug|Any CPU 133 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Release|Any CPU.ActiveCfg = Release|Any CPU 134 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Release|Any CPU.Build.0 = Release|Any CPU 135 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 136 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Release|Mixed Platforms.Build.0 = Release|Any CPU 137 | {6D68DFA2-6271-4847-96FA-631AE49D2CCA}.Release|x86.ActiveCfg = Release|Any CPU 138 | EndGlobalSection 139 | GlobalSection(SolutionProperties) = preSolution 140 | HideSolutionNode = FALSE 141 | EndGlobalSection 142 | EndGlobal 143 | -------------------------------------------------------------------------------- /AzureNetQ/AzureAdvancedBus.cs: -------------------------------------------------------------------------------- 1 | namespace AzureNetQ 2 | { 3 | using System; 4 | using System.Collections.Concurrent; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Security; 9 | using System.Security.Cryptography.X509Certificates; 10 | 11 | using Microsoft.ServiceBus; 12 | using Microsoft.ServiceBus.Messaging; 13 | 14 | public interface IAzureAdvancedBus 15 | { 16 | QueueClient QueueDeclare(string name, bool autoDelete = false); 17 | 18 | void QueueDelete(string name); 19 | 20 | TopicClient TopicFind(string name); 21 | 22 | TopicClient TopicDeclare(string name, bool requiresDuplicateDetection); 23 | 24 | void TopicDelete(string topic); 25 | 26 | SubscriptionClient SubscriptionDeclare( 27 | string name, 28 | List topic, 29 | string subscription, 30 | ReceiveMode receiveMode, 31 | bool requiresDuplicateDetection, 32 | int maxDeliveryCount); 33 | } 34 | 35 | public class AzureAdvancedBus : IAzureAdvancedBus 36 | { 37 | private readonly IAzureNetQLogger logger; 38 | 39 | private readonly IConnectionConfiguration configuration; 40 | 41 | private readonly ConcurrentDictionary queues; 42 | 43 | private readonly ConcurrentDictionary topics; 44 | 45 | private readonly ConcurrentDictionary subscriptions; 46 | 47 | private readonly NamespaceManager namespaceManager; 48 | 49 | private readonly MessagingFactory messagingFactory; 50 | 51 | public AzureAdvancedBus(IAzureNetQLogger logger, IConnectionConfiguration configuration) 52 | { 53 | this.namespaceManager = NamespaceManager.CreateFromConnectionString(configuration.ConnectionString); 54 | 55 | var pairs = configuration.ConnectionString.Split(';').Select(o => o.Split('=')).Where(o => o.Length > 1); 56 | 57 | var dictionary = pairs.ToDictionary(key => key[0], value => value[1]); 58 | var address = this.namespaceManager.Address; 59 | 60 | int port; 61 | if (dictionary.ContainsKey("Endpoint") && dictionary.ContainsKey("RuntimePort") 62 | && int.TryParse(dictionary["RuntimePort"], out port)) 63 | { 64 | var template = new Uri(string.Format("{0}", dictionary["Endpoint"])); 65 | address = new UriBuilder(template.Scheme, template.Host, port, template.PathAndQuery).Uri; 66 | } 67 | 68 | var mfs = new MessagingFactorySettings 69 | { 70 | TokenProvider = this.namespaceManager.Settings.TokenProvider, 71 | NetMessagingTransportSettings = 72 | { 73 | BatchFlushInterval = 74 | configuration 75 | .BatchingInterval 76 | } 77 | }; 78 | 79 | this.messagingFactory = MessagingFactory.Create(address, mfs); 80 | 81 | this.queues = new ConcurrentDictionary(); 82 | this.topics = new ConcurrentDictionary(); 83 | this.subscriptions = new ConcurrentDictionary(); 84 | 85 | this.logger = logger; 86 | this.configuration = configuration; 87 | } 88 | 89 | public virtual QueueClient QueueDeclare(string name, bool autoDelete = false) 90 | { 91 | Preconditions.CheckNotNull(name, "name"); 92 | 93 | return this.queues.GetOrAdd( 94 | name, 95 | s => 96 | { 97 | #if DEBUG 98 | SslValidator.OverrideValidation(); 99 | #endif 100 | if (!namespaceManager.QueueExists(s)) 101 | { 102 | var description = new QueueDescription(s); 103 | if (autoDelete) 104 | { 105 | description.AutoDeleteOnIdle = TimeSpan.FromMinutes(5); 106 | } 107 | 108 | description.DefaultMessageTimeToLive = TimeSpan.FromDays(5); 109 | description.EnableDeadLetteringOnMessageExpiration = true; 110 | description.LockDuration = TimeSpan.FromSeconds(15); 111 | 112 | logger.DebugWrite("Declared Queue: '{0}'", name); 113 | namespaceManager.CreateQueue(description); 114 | } 115 | 116 | var client = messagingFactory.CreateQueueClient(s); 117 | client.PrefetchCount = configuration.PrefetchCount; 118 | 119 | return client; 120 | }); 121 | } 122 | 123 | public SubscriptionClient SubscriptionDeclare( 124 | string name, 125 | List topicNames, 126 | string subscription, 127 | ReceiveMode receiveMode, 128 | bool requiresDuplicateDetection, 129 | int maxDeliveryCount) 130 | { 131 | var topicClient = this.TopicDeclare(name, requiresDuplicateDetection); 132 | 133 | return this.subscriptions.GetOrAdd( 134 | BuildSubscriptionKey(name, subscription, topicNames), 135 | s => 136 | { 137 | #if DEBUG 138 | SslValidator.OverrideValidation(); 139 | #endif 140 | var parts = new List { subscription }; 141 | parts.AddRange(topicNames); 142 | 143 | var subscriptionId = 144 | string.Join("-", parts.Where(o => !string.IsNullOrEmpty(o))) 145 | .Replace("#", "_") 146 | .Replace("*", "_"); 147 | 148 | if (!namespaceManager.SubscriptionExists(topicClient.Path, subscriptionId)) 149 | { 150 | var description = new SubscriptionDescription(topicClient.Path, subscriptionId) 151 | { 152 | MaxDeliveryCount = maxDeliveryCount, 153 | DefaultMessageTimeToLive = TimeSpan.FromDays(5), 154 | EnableDeadLetteringOnMessageExpiration = true, 155 | LockDuration = TimeSpan.FromMinutes(1) 156 | }; 157 | 158 | if (topicNames.Any()) 159 | { 160 | var expression = string.Join( 161 | " OR ", 162 | topicNames.Select( 163 | o => string.Format("user.topic LIKE '{0}'", TransformWildcards(o)))); 164 | 165 | var filter = new SqlFilter(expression); 166 | namespaceManager.CreateSubscription(description, filter); 167 | 168 | logger.DebugWrite( 169 | "Declared Subscription: '{0}' on Topic {1} with filter {2}", 170 | subscription, 171 | topicClient.Path, 172 | filter); 173 | } 174 | else 175 | { 176 | namespaceManager.CreateSubscription(description); 177 | logger.DebugWrite( 178 | "Declared Subscription: '{0}' on Topic {1}", 179 | subscription, 180 | topicClient.Path); 181 | } 182 | } 183 | 184 | return messagingFactory.CreateSubscriptionClient(topicClient.Path, subscriptionId, receiveMode); 185 | }); 186 | } 187 | 188 | public TopicClient TopicFind(string name) 189 | { 190 | var topicClient = this.topics.GetOrAdd( 191 | name, 192 | n => 193 | { 194 | #if DEBUG 195 | SslValidator.OverrideValidation(); 196 | #endif 197 | return this.namespaceManager.TopicExists(n) ? this.messagingFactory.CreateTopicClient(n) : null; 198 | }); 199 | 200 | return topicClient; 201 | } 202 | 203 | public TopicClient TopicDeclare(string name, bool requiresDuplicateDetection) 204 | { 205 | var topicClient = this.topics.GetOrAdd( 206 | name, 207 | n => 208 | { 209 | #if DEBUG 210 | SslValidator.OverrideValidation(); 211 | #endif 212 | if (!this.namespaceManager.TopicExists(n)) 213 | { 214 | var description = new TopicDescription(n) { RequiresDuplicateDetection = requiresDuplicateDetection }; 215 | 216 | this.logger.DebugWrite("Declared Topic: '{0}'", n); 217 | this.namespaceManager.CreateTopic(description); 218 | } 219 | 220 | var client = this.messagingFactory.CreateTopicClient(n); 221 | return client; 222 | }); 223 | return topicClient; 224 | } 225 | 226 | public void QueueDelete(string name) 227 | { 228 | QueueClient toRemove; 229 | if (this.queues.TryRemove(name, out toRemove)) 230 | { 231 | #if DEBUG 232 | SslValidator.OverrideValidation(); 233 | #endif 234 | if (this.namespaceManager.QueueExists(name)) 235 | { 236 | this.namespaceManager.DeleteQueue(name); 237 | } 238 | } 239 | } 240 | 241 | public void TopicDelete(string topic) 242 | { 243 | TopicClient toRemove; 244 | if (this.topics.TryRemove(topic, out toRemove)) 245 | { 246 | #if DEBUG 247 | SslValidator.OverrideValidation(); 248 | #endif 249 | if (this.namespaceManager.TopicExists(topic)) 250 | { 251 | this.namespaceManager.DeleteTopic(topic); 252 | } 253 | } 254 | } 255 | 256 | private static string TransformWildcards(string o) 257 | { 258 | return o.Replace('#', '%').Replace('*', '%'); 259 | } 260 | 261 | private static string BuildSubscriptionKey(string name, string subscription, IEnumerable topics) 262 | { 263 | return string.Format("{0}{1}{2}", name, subscription, string.Join(string.Empty, topics)); 264 | } 265 | 266 | public static class SslValidator 267 | { 268 | public static void OverrideValidation() 269 | { 270 | ServicePointManager.ServerCertificateValidationCallback = 271 | OnValidateCertificate; 272 | ServicePointManager.Expect100Continue = true; 273 | } 274 | 275 | private static bool OnValidateCertificate( 276 | object sender, 277 | X509Certificate certificate, 278 | X509Chain chain, 279 | SslPolicyErrors sslPolicyErrors) 280 | { 281 | return true; 282 | } 283 | } 284 | } 285 | } --------------------------------------------------------------------------------