Some initial ideas worked out, with a generous amount of todos
This commit is contained in:
parent
a3b8b705ab
commit
97b654737a
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.vs/
|
||||
bin/
|
||||
obj/
|
||||
packages/
|
9
Tapeti/Annotations/MessageHandlerAttribute.cs
Normal file
9
Tapeti/Annotations/MessageHandlerAttribute.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Tapeti.Annotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class MessageHandlerAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
11
Tapeti/Annotations/QueueAttribute.cs
Normal file
11
Tapeti/Annotations/QueueAttribute.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Tapeti.Annotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class QueueAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; } = null;
|
||||
public bool Dynamic { get; set; } = false;
|
||||
}
|
||||
}
|
13
Tapeti/Connection/TapetiPublisher.cs
Normal file
13
Tapeti/Connection/TapetiPublisher.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Tapeti.Connection
|
||||
{
|
||||
public class TapetiPublisher : IPublisher
|
||||
{
|
||||
private readonly TapetiWorker worker;
|
||||
|
||||
|
||||
public TapetiPublisher(TapetiWorker worker)
|
||||
{
|
||||
this.worker = worker;
|
||||
}
|
||||
}
|
||||
}
|
25
Tapeti/Connection/TapetiSubscriber.cs
Normal file
25
Tapeti/Connection/TapetiSubscriber.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Tapeti.Connection
|
||||
{
|
||||
public class TapetiSubscriber : ISubscriber
|
||||
{
|
||||
private readonly TapetiWorker worker;
|
||||
|
||||
|
||||
public TapetiSubscriber(TapetiWorker worker, IEnumerable<IMessageHandlerRegistration> registrations)
|
||||
{
|
||||
this.worker = worker;
|
||||
|
||||
ApplyTopology(registrations);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void ApplyTopology(IEnumerable<IMessageHandlerRegistration> registrations)
|
||||
{
|
||||
foreach (var registration in registrations)
|
||||
registration.ApplyTopology(worker.GetChannel());
|
||||
}
|
||||
}
|
||||
}
|
58
Tapeti/Connection/TapetiWorker.cs
Normal file
58
Tapeti/Connection/TapetiWorker.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.Threading.Tasks;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace Tapeti.Connection
|
||||
{
|
||||
public class TapetiWorker
|
||||
{
|
||||
public string HostName { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string VirtualHost { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
|
||||
private IConnection connection;
|
||||
private IModel channel;
|
||||
|
||||
|
||||
public Task Close()
|
||||
{
|
||||
if (channel != null)
|
||||
{
|
||||
channel.Dispose();
|
||||
channel = null;
|
||||
}
|
||||
|
||||
if (connection != null)
|
||||
{
|
||||
connection.Dispose();
|
||||
connection = null;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public IModel GetChannel()
|
||||
{
|
||||
if (channel != null)
|
||||
return channel;
|
||||
|
||||
var connectionFactory = new ConnectionFactory
|
||||
{
|
||||
HostName = HostName,
|
||||
Port = Port,
|
||||
VirtualHost = VirtualHost,
|
||||
UserName = Username,
|
||||
Password = Password,
|
||||
AutomaticRecoveryEnabled = true
|
||||
};
|
||||
|
||||
connection = connectionFactory.CreateConnection();
|
||||
channel = connection.CreateModel();
|
||||
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
}
|
12
Tapeti/Default/DefaultControllerFactory.cs
Normal file
12
Tapeti/Default/DefaultControllerFactory.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Tapeti.Default
|
||||
{
|
||||
public class DefaultControllerFactory : IControllerFactory
|
||||
{
|
||||
public object CreateController(Type controllerType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
6
Tapeti/Default/DefaultRoutingKeyStrategy.cs
Normal file
6
Tapeti/Default/DefaultRoutingKeyStrategy.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Tapeti.Default
|
||||
{
|
||||
public class DefaultRoutingKeyStrategy : IRoutingKeyStrategy
|
||||
{
|
||||
}
|
||||
}
|
9
Tapeti/IControllerFactory.cs
Normal file
9
Tapeti/IControllerFactory.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Tapeti
|
||||
{
|
||||
public interface IControllerFactory
|
||||
{
|
||||
object CreateController(Type controllerType);
|
||||
}
|
||||
}
|
13
Tapeti/IMessageHandlerRegistration.cs
Normal file
13
Tapeti/IMessageHandlerRegistration.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Threading.Tasks;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace Tapeti
|
||||
{
|
||||
public interface IMessageHandlerRegistration
|
||||
{
|
||||
void ApplyTopology(IModel channel);
|
||||
|
||||
bool Accept(object message);
|
||||
Task Visit(object message);
|
||||
}
|
||||
}
|
6
Tapeti/IPublisher.cs
Normal file
6
Tapeti/IPublisher.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Tapeti
|
||||
{
|
||||
public interface IPublisher
|
||||
{
|
||||
}
|
||||
}
|
6
Tapeti/IRoutingKeyStrategy.cs
Normal file
6
Tapeti/IRoutingKeyStrategy.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Tapeti
|
||||
{
|
||||
public interface IRoutingKeyStrategy
|
||||
{
|
||||
}
|
||||
}
|
6
Tapeti/ISubscriber.cs
Normal file
6
Tapeti/ISubscriber.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Tapeti
|
||||
{
|
||||
public interface ISubscriber
|
||||
{
|
||||
}
|
||||
}
|
36
Tapeti/Properties/AssemblyInfo.cs
Normal file
36
Tapeti/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Tapeti")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Hewlett-Packard Company")]
|
||||
[assembly: AssemblyProduct("Tapeti")]
|
||||
[assembly: AssemblyCopyright("Copyright © Hewlett-Packard Company 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("8ab4fd33-4aaa-465c-8579-9db3f3b23813")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
105
Tapeti/Registration/AbstractControllerRegistration.cs
Normal file
105
Tapeti/Registration/AbstractControllerRegistration.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using RabbitMQ.Client;
|
||||
using Tapeti.Annotations;
|
||||
|
||||
namespace Tapeti.Registration
|
||||
{
|
||||
using MessageHandlerAction = Func<object, Task>;
|
||||
|
||||
public abstract class AbstractControllerRegistration : IMessageHandlerRegistration
|
||||
{
|
||||
private readonly IControllerFactory controllerFactory;
|
||||
private readonly Type controllerType;
|
||||
private readonly Dictionary<Type, List<MessageHandlerAction>> messageHandlers = new Dictionary<Type, List<MessageHandlerAction>>();
|
||||
|
||||
|
||||
protected AbstractControllerRegistration(IControllerFactory controllerFactory, Type controllerType)
|
||||
{
|
||||
this.controllerFactory = controllerFactory;
|
||||
this.controllerType = controllerType;
|
||||
|
||||
// ReSharper disable once VirtualMemberCallInConstructor - I know. What do you think this is, C++?
|
||||
GetMessageHandlers((type, handler) =>
|
||||
{
|
||||
if (!messageHandlers.ContainsKey(type))
|
||||
messageHandlers.Add(type, new List<MessageHandlerAction> { handler });
|
||||
else
|
||||
messageHandlers[type].Add(handler);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected virtual void GetMessageHandlers(Action<Type, MessageHandlerAction> add)
|
||||
{
|
||||
foreach (var method in GetType().GetMembers()
|
||||
.Where(m => m.MemberType == MemberTypes.Method && m.IsDefined(typeof(MessageHandlerAttribute), true))
|
||||
.Select(m => (MethodInfo)m))
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
|
||||
if (parameters.Length != 1 || !parameters[0].ParameterType.IsClass)
|
||||
throw new ArgumentException($"Method {0} does not have a single object parameter", method.Name);
|
||||
|
||||
var messageType = parameters[0].ParameterType;
|
||||
|
||||
if (method.ReturnType == typeof(void))
|
||||
add(messageType, CreateSyncMessageHandler(method));
|
||||
else if (method.ReturnType == typeof(Task))
|
||||
add(messageType, CreateAsyncMessageHandler(method));
|
||||
else
|
||||
throw new ArgumentException($"Method {0} needs to return void or a Task", method.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected IEnumerable<Type> GetMessageTypes()
|
||||
{
|
||||
return messageHandlers.Keys;
|
||||
}
|
||||
|
||||
|
||||
public abstract void ApplyTopology(IModel channel);
|
||||
|
||||
|
||||
public bool Accept(object message)
|
||||
{
|
||||
return messageHandlers.ContainsKey(message.GetType());
|
||||
}
|
||||
|
||||
|
||||
public Task Visit(object message)
|
||||
{
|
||||
var registeredHandlers = messageHandlers[message.GetType()];
|
||||
if (registeredHandlers != null)
|
||||
return Task.WhenAll(registeredHandlers.Select(messageHandler => messageHandler(message)));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
protected virtual MessageHandlerAction CreateSyncMessageHandler(MethodInfo method)
|
||||
{
|
||||
return message =>
|
||||
{
|
||||
var controller = controllerFactory.CreateController(controllerType);
|
||||
method.Invoke(controller, new[] { message });
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
protected virtual MessageHandlerAction CreateAsyncMessageHandler(MethodInfo method)
|
||||
{
|
||||
return message =>
|
||||
{
|
||||
var controller = controllerFactory.CreateController(controllerType);
|
||||
return (Task)method.Invoke(controller, new[] { message });
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
31
Tapeti/Registration/ControllerDynamicQueueRegistration.cs
Normal file
31
Tapeti/Registration/ControllerDynamicQueueRegistration.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace Tapeti.Registration
|
||||
{
|
||||
public class ControllerDynamicQueueRegistration : AbstractControllerRegistration
|
||||
{
|
||||
private readonly IRoutingKeyStrategy routingKeyStrategy;
|
||||
|
||||
|
||||
public ControllerDynamicQueueRegistration(IControllerFactory controllerFactory, IRoutingKeyStrategy routingKeyStrategy, Type controllerType)
|
||||
: base(controllerFactory, controllerType)
|
||||
{
|
||||
this.routingKeyStrategy = routingKeyStrategy;
|
||||
}
|
||||
|
||||
|
||||
public override void ApplyTopology(IModel channel)
|
||||
{
|
||||
var queue = channel.QueueDeclare();
|
||||
|
||||
foreach (var messageType in GetMessageTypes())
|
||||
{
|
||||
//TODO use routing key attribute(s) for method or use strategy
|
||||
//TODO use exchange attribute or default setting
|
||||
|
||||
//channel.QueueBind(queue.QueueName, );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
Tapeti/Registration/ControllerQueueRegistration.cs
Normal file
21
Tapeti/Registration/ControllerQueueRegistration.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace Tapeti.Registration
|
||||
{
|
||||
public class ControllerQueueRegistration : AbstractControllerRegistration
|
||||
{
|
||||
private readonly string queueName;
|
||||
|
||||
public ControllerQueueRegistration(IControllerFactory controllerFactory, IRoutingKeyStrategy routingKeyStrategy, Type controllerType, string queueName) : base(controllerFactory, controllerType)
|
||||
{
|
||||
this.queueName = queueName;
|
||||
}
|
||||
|
||||
|
||||
public override void ApplyTopology(IModel channel)
|
||||
{
|
||||
channel.QueueDeclarePassive(queueName);
|
||||
}
|
||||
}
|
||||
}
|
77
Tapeti/Tapeti.csproj
Normal file
77
Tapeti/Tapeti.csproj
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Tapeti</RootNamespace>
|
||||
<AssemblyName>Tapeti</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="RabbitMQ.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89e7d7c5feba84ce, processorArchitecture=MSIL">
|
||||
<HintPath>packages\RabbitMQ.Client.4.1.1\lib\net451\RabbitMQ.Client.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Annotations\MessageHandlerAttribute.cs" />
|
||||
<Compile Include="Annotations\QueueAttribute.cs" />
|
||||
<Compile Include="Connection\TapetiPublisher.cs" />
|
||||
<Compile Include="Connection\TapetiSubscriber.cs" />
|
||||
<Compile Include="Connection\TapetiWorker.cs" />
|
||||
<Compile Include="Default\DefaultControllerFactory.cs" />
|
||||
<Compile Include="Default\DefaultRoutingKeyStrategy.cs" />
|
||||
<Compile Include="IControllerFactory.cs" />
|
||||
<Compile Include="IPublisher.cs" />
|
||||
<Compile Include="IRoutingKeyStrategy.cs" />
|
||||
<Compile Include="IMessageHandlerRegistration.cs" />
|
||||
<Compile Include="ISubscriber.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Registration\AbstractControllerRegistration.cs" />
|
||||
<Compile Include="Registration\ControllerDynamicQueueRegistration.cs" />
|
||||
<Compile Include="Registration\ControllerQueueRegistration.cs" />
|
||||
<Compile Include="TapetiConnection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
22
Tapeti/Tapeti.sln
Normal file
22
Tapeti/Tapeti.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tapeti", "Tapeti.csproj", "{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8AB4FD33-4AAA-465C-8579-9DB3F3B23813}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
138
Tapeti/TapetiConnection.cs
Normal file
138
Tapeti/TapetiConnection.cs
Normal file
@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Tapeti.Annotations;
|
||||
using Tapeti.Connection;
|
||||
using Tapeti.Default;
|
||||
using Tapeti.Registration;
|
||||
|
||||
namespace Tapeti
|
||||
{
|
||||
public class TapetiConnection : IDisposable
|
||||
{
|
||||
public string HostName { get; set; } = "localhost";
|
||||
public int Port { get; set; } = 5672;
|
||||
public string VirtualHost { get; set; } = "/";
|
||||
public string Username { get; set; } = "guest";
|
||||
public string Password { get; set; } = "guest";
|
||||
|
||||
public IControllerFactory ControllerFactory
|
||||
{
|
||||
get { return controllerFactory ?? (controllerFactory = new DefaultControllerFactory()); }
|
||||
set { controllerFactory = value; }
|
||||
}
|
||||
|
||||
|
||||
public IRoutingKeyStrategy RoutingKeyStrategy
|
||||
{
|
||||
get { return routingKeyStrategy ?? (routingKeyStrategy = new DefaultRoutingKeyStrategy()); }
|
||||
set { routingKeyStrategy = value; }
|
||||
}
|
||||
|
||||
|
||||
private IControllerFactory controllerFactory;
|
||||
private IRoutingKeyStrategy routingKeyStrategy;
|
||||
private List<IMessageHandlerRegistration> registrations;
|
||||
private TapetiWorker worker;
|
||||
|
||||
|
||||
|
||||
public TapetiConnection WithControllerFactory(IControllerFactory factory)
|
||||
{
|
||||
controllerFactory = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public TapetiConnection RegisterController(Type type)
|
||||
{
|
||||
var queueAttribute = type.GetCustomAttribute<QueueAttribute>();
|
||||
if (queueAttribute == null)
|
||||
throw new ArgumentException("Queue attribute required on class", nameof(type));
|
||||
|
||||
if (queueAttribute.Dynamic)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(queueAttribute.Name))
|
||||
throw new ArgumentException("Dynamic queue attributes must not have a Name");
|
||||
|
||||
GetRegistrations().Add(new ControllerDynamicQueueRegistration(controllerFactory, routingKeyStrategy, type));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(queueAttribute.Name))
|
||||
throw new ArgumentException("Non-dynamic queue attribute must have a Name");
|
||||
|
||||
GetRegistrations().Add(new ControllerQueueRegistration(controllerFactory, routingKeyStrategy, type, queueAttribute.Name));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public TapetiConnection RegisterAllControllers(Assembly assembly)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes().Where(t => t.IsDefined(typeof(QueueAttribute))))
|
||||
RegisterController(type);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public TapetiConnection RegisterAllControllers()
|
||||
{
|
||||
return RegisterAllControllers(Assembly.GetCallingAssembly());
|
||||
}
|
||||
|
||||
|
||||
public ISubscriber Subscribe()
|
||||
{
|
||||
if (registrations == null || registrations.Count == 0)
|
||||
throw new ArgumentException("No controllers registered");
|
||||
|
||||
return new TapetiSubscriber(GetWorker(), registrations);
|
||||
}
|
||||
|
||||
|
||||
public IPublisher GetPublisher()
|
||||
{
|
||||
return new TapetiPublisher(GetWorker());
|
||||
}
|
||||
|
||||
|
||||
public async Task Close()
|
||||
{
|
||||
if (worker != null)
|
||||
{
|
||||
await worker.Close();
|
||||
worker = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Close().Wait();
|
||||
}
|
||||
|
||||
|
||||
protected List<IMessageHandlerRegistration> GetRegistrations()
|
||||
{
|
||||
return registrations ?? (registrations = new List<IMessageHandlerRegistration>());
|
||||
}
|
||||
|
||||
|
||||
protected TapetiWorker GetWorker()
|
||||
{
|
||||
return worker ?? (worker = new TapetiWorker
|
||||
{
|
||||
HostName = HostName,
|
||||
Port = Port,
|
||||
VirtualHost = VirtualHost,
|
||||
Username = Username,
|
||||
Password = Password
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
4
Tapeti/packages.config
Normal file
4
Tapeti/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="RabbitMQ.Client" version="4.1.1" targetFramework="net461" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user