Skip to content

Commit 126e514

Browse files
Ticket #111: Can load plugins
1 parent e218a50 commit 126e514

12 files changed

Lines changed: 161 additions & 10 deletions

File tree

FaasNet.EventMesh.sln

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.31624.102
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.1.32328.378
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02. Core Layer", "02. Core Layer", "{6E495E0A-0DC8-4E42-8C58-3C48506D3D24}"
77
EndProject
@@ -69,6 +69,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05. CLI Layer", "05. CLI La
6969
EndProject
7070
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaasNet.EventMeshCTL.CLI", "src\EventMesh\FaasNet.EventMeshCTL.CLI\FaasNet.EventMeshCTL.CLI.csproj", "{294141B6-1F8D-43D9-BF3E-5A86FFD8F38D}"
7171
EndProject
72+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaasNet.Plugin", "src\Common\FaasNet.Plugin\FaasNet.Plugin.csproj", "{EEAF94A6-E863-4349-8A44-74DCC55F6607}"
73+
EndProject
7274
Global
7375
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7476
Debug|Any CPU = Debug|Any CPU
@@ -167,6 +169,10 @@ Global
167169
{294141B6-1F8D-43D9-BF3E-5A86FFD8F38D}.Debug|Any CPU.Build.0 = Debug|Any CPU
168170
{294141B6-1F8D-43D9-BF3E-5A86FFD8F38D}.Release|Any CPU.ActiveCfg = Release|Any CPU
169171
{294141B6-1F8D-43D9-BF3E-5A86FFD8F38D}.Release|Any CPU.Build.0 = Release|Any CPU
172+
{EEAF94A6-E863-4349-8A44-74DCC55F6607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
173+
{EEAF94A6-E863-4349-8A44-74DCC55F6607}.Debug|Any CPU.Build.0 = Debug|Any CPU
174+
{EEAF94A6-E863-4349-8A44-74DCC55F6607}.Release|Any CPU.ActiveCfg = Release|Any CPU
175+
{EEAF94A6-E863-4349-8A44-74DCC55F6607}.Release|Any CPU.Build.0 = Release|Any CPU
170176
EndGlobalSection
171177
GlobalSection(SolutionProperties) = preSolution
172178
HideSolutionNode = FALSE
@@ -198,6 +204,7 @@ Global
198204
{D581D830-5A97-451F-96C5-8AC513EC308D} = {8B617B76-FFD2-4DBE-921E-B7DB73309530}
199205
{21CC76FF-FA0A-4FF2-A0A1-78A8C107FCEE} = {F9148CB9-8CA8-43BA-85F2-46C94AF624D7}
200206
{294141B6-1F8D-43D9-BF3E-5A86FFD8F38D} = {E7E305E3-DDFE-4523-8343-82C62884A323}
207+
{EEAF94A6-E863-4349-8A44-74DCC55F6607} = {7A13262A-D1E6-4210-BA95-03A0741CBFA4}
201208
EndGlobalSection
202209
GlobalSection(ExtensibilityGlobals) = postSolution
203210
SolutionGuid = {B9BD3B8C-B2C9-468F-BF54-66BFE9B565EC}

default.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ task publishDocker {
6060
exec { dotnet publish $source_dir\EventMesh\FaasNet.EventMesh.Runtime.Website\FaasNet.EventMesh.Runtime.Website.csproj -c $config -o $result_dir\services\EventMeshServer }
6161
}
6262

63+
task publishEventMeshPlugins {
64+
exec { dotnet publish $source_dir\EventMesh\FaasNet.EventMesh.Protocols.AMQP\FaasNet.EventMesh.Protocols.AMQP.csproj -c $config -o $result_dir\eventMeshServicePlugins\FaasNet.EventMesh.Protocols.AMQP }
65+
}
66+
6367
task publishEventMeshService {
6468
exec { dotnet publish $source_dir\EventMesh\FaasNet.EventMesh.Service\FaasNet.EventMesh.Service.csproj -c $config -o $result_dir\eventMeshService }
6569
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net5.0</TargetFramework>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
7+
</ItemGroup>
8+
<ItemGroup>
9+
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
10+
</ItemGroup>
11+
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace FaasNet.Plugin
4+
{
5+
public interface IPlugin<T> where T : class
6+
{
7+
void Load(IServiceCollection services, T options);
8+
}
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace FaasNet.Plugin
2+
{
3+
public class PluginEntry
4+
{
5+
public string DllName { get; set; }
6+
public object Configuration { get; set; }
7+
}
8+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using McMaster.NETCore.Plugins;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using System;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Reflection;
7+
using System.Text.Json;
8+
9+
namespace FaasNet.Plugin
10+
{
11+
public class PluginEntryDiscovery
12+
{
13+
public static bool TryExtract(string pluginDirectoryPath, out IDiscoveredPlugin discoveryPlugin)
14+
{
15+
discoveryPlugin = null;
16+
var appsettingsFilePath = Path.Combine(pluginDirectoryPath, "appsettings.json");
17+
if (!File.Exists(appsettingsFilePath)) return false;
18+
var pluginEntry = JsonSerializer.Deserialize<PluginEntry>(File.ReadAllText(appsettingsFilePath));
19+
var dllPath = Path.Combine(pluginDirectoryPath, pluginEntry.DllName);
20+
if(!File.Exists(dllPath)) return false;
21+
var loader = PluginLoader.CreateFromAssemblyFile(
22+
dllPath,
23+
sharedTypes: new[] { typeof(IPlugin<>), typeof(IServiceCollection) });
24+
var assembly = loader.LoadDefaultAssembly();
25+
var types = assembly.GetTypes();
26+
var pluginType = types.FirstOrDefault(t => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition().Name.StartsWith("IPlugin")));
27+
if (pluginType == null) return false;
28+
var optionType = pluginType.GetInterfaces()[0].GenericTypeArguments[0];
29+
dynamic option = Activator.CreateInstance(optionType);
30+
var serializedConfiguration = string.Empty;
31+
if(pluginEntry.Configuration != null) serializedConfiguration = JsonSerializer.Serialize(pluginEntry.Configuration);
32+
if(!string.IsNullOrWhiteSpace(serializedConfiguration)) option = JsonSerializer.Deserialize(serializedConfiguration, optionType, new JsonSerializerOptions
33+
{
34+
PropertyNameCaseInsensitive = true
35+
});
36+
discoveryPlugin = new DiscoveredPlugin(pluginType, option);
37+
return true;
38+
}
39+
40+
private class DiscoveredPlugin : IDiscoveredPlugin
41+
{
42+
private readonly Type _pluginType;
43+
private readonly dynamic _option;
44+
45+
public DiscoveredPlugin(Type pluginType, dynamic option)
46+
{
47+
_pluginType = pluginType;
48+
_option = option;
49+
}
50+
51+
public void Load(IServiceCollection services)
52+
{
53+
var pluginInstance = Activator.CreateInstance(_pluginType);
54+
var loadFn = _pluginType.GetMethod("Load", BindingFlags.Public | BindingFlags.Instance);
55+
loadFn.Invoke(pluginInstance, new object[] { services, _option });
56+
}
57+
}
58+
}
59+
60+
public interface IDiscoveredPlugin
61+
{
62+
void Load(IServiceCollection services);
63+
}
64+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using FaasNet.Plugin;
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
namespace FaasNet.EventMesh.Protocols.AMQP
5+
{
6+
public class EventMeshAMQPPlugin : IPlugin<EventMeshAMQPOptions>
7+
{
8+
public void Load(IServiceCollection services, EventMeshAMQPOptions options)
9+
{
10+
services.AddAMQPProtocol(o =>
11+
{
12+
o.Port = options.Port;
13+
o.EventMeshPort = options.EventMeshPort;
14+
o.EventMeshVpn = options.EventMeshVpn;
15+
o.EventMeshUrl = options.EventMeshUrl;
16+
o.MaxFrameSize = options.MaxFrameSize;
17+
o.MaxChannel = options.MaxChannel;
18+
o.SessionLinkCredit = options.SessionLinkCredit;
19+
o.SessionLinkCredit = options.SessionLinkCredit;
20+
});
21+
}
22+
}
23+
}

src/EventMesh/FaasNet.EventMesh.Protocols.AMQP/FaasNet.EventMesh.Protocols.AMQP.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
1010
</ItemGroup>
1111
<ItemGroup>
12+
<ProjectReference Include="..\..\Common\FaasNet.Plugin\FaasNet.Plugin.csproj" />
1213
<ProjectReference Include="..\FaasNet.EventMesh.Protocols\FaasNet.EventMesh.Protocols.csproj" />
1314
</ItemGroup>
15+
<ItemGroup>
16+
<None Update="appsettings.json">
17+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
18+
</None>
19+
</ItemGroup>
1420
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"DllName": "FaasNet.EventMesh.Protocols.AMQP.dll",
3+
"Configuration": {
4+
"Port": 5672
5+
}
6+
}

src/EventMesh/FaasNet.EventMesh.Service/FaasNet.EventMesh.Service.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk.Worker">
1+
<Project Sdk="Microsoft.NET.Sdk.Worker">
22
<PropertyGroup>
33
<OutputType>Exe</OutputType>
44
<TargetFramework>net6.0</TargetFramework>
@@ -12,6 +12,7 @@
1212
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
1313
</ItemGroup>
1414
<ItemGroup>
15+
<ProjectReference Include="..\..\Common\FaasNet.Plugin\FaasNet.Plugin.csproj" />
1516
<ProjectReference Include="..\..\RaftConsensus\FaasNet.RaftConsensus.RocksDB\FaasNet.RaftConsensus.RocksDB.csproj" />
1617
<ProjectReference Include="..\FaasNet.EventMesh.Runtime\FaasNet.EventMesh.Runtime.csproj" />
1718
</ItemGroup>

0 commit comments

Comments
 (0)