mirror of
https://github.com/cadmium-im/zirconium-sharp.git
synced 2024-11-09 12:11:04 +00:00
Implement inter-plugin communication system + add some showcase of it
This commit is contained in:
parent
a829042581
commit
bd74068d6f
11
src/Zirconium/Core/Plugins/IPC/ExportedIPCMethod.cs
Normal file
11
src/Zirconium/Core/Plugins/IPC/ExportedIPCMethod.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
namespace Zirconium.Core.Plugins.IPC
|
||||||
|
{
|
||||||
|
public class ExportedIPCMethod
|
||||||
|
{
|
||||||
|
public object Service { get; set; }
|
||||||
|
public string MethodName { get; set; }
|
||||||
|
public MethodInfo Method { get; set; }
|
||||||
|
}
|
||||||
|
}
|
13
src/Zirconium/Core/Plugins/IPC/ExportedIPCMethodAttribute.cs
Normal file
13
src/Zirconium/Core/Plugins/IPC/ExportedIPCMethodAttribute.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace Zirconium.Core.Plugins.IPC
|
||||||
|
{
|
||||||
|
[System.AttributeUsage(System.AttributeTargets.Method)]
|
||||||
|
public class ExportedIPCMethodAttribute : System.Attribute
|
||||||
|
{
|
||||||
|
public string MethodName { get; private set; }
|
||||||
|
|
||||||
|
public ExportedIPCMethodAttribute(string name)
|
||||||
|
{
|
||||||
|
this.MethodName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
src/Zirconium/Core/Plugins/IPC/IPCRouter.cs
Normal file
53
src/Zirconium/Core/Plugins/IPC/IPCRouter.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Zirconium.Utils;
|
||||||
|
|
||||||
|
namespace Zirconium.Core.Plugins.IPC
|
||||||
|
{
|
||||||
|
public class IPCRouter
|
||||||
|
{
|
||||||
|
private IDictionary<string, IList<ExportedIPCMethod>> methodTable = new Dictionary<string, IList<ExportedIPCMethod>>();
|
||||||
|
|
||||||
|
public void RegisterIPCService(string pluginName, object service)
|
||||||
|
{
|
||||||
|
Type t = service.GetType();
|
||||||
|
var exportedMethods = t.GetMethods()
|
||||||
|
.Where(m => m.GetCustomAttributes(typeof(ExportedIPCMethodAttribute), false).Length > 0)
|
||||||
|
.ToArray();
|
||||||
|
foreach (var m in exportedMethods)
|
||||||
|
{
|
||||||
|
var attr = (ExportedIPCMethodAttribute)m.GetCustomAttributes(typeof(ExportedIPCMethodAttribute), false).First();
|
||||||
|
var exportedMethod = new ExportedIPCMethod();
|
||||||
|
exportedMethod.Service = service;
|
||||||
|
exportedMethod.MethodName = attr.MethodName;
|
||||||
|
exportedMethod.Method = m;
|
||||||
|
if (methodTable.GetValueOrDefault(pluginName, null) == null)
|
||||||
|
{
|
||||||
|
methodTable[pluginName] = new List<ExportedIPCMethod>();
|
||||||
|
}
|
||||||
|
methodTable[pluginName].Add(exportedMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<dynamic> MakeRequest(string pluginName, string methodName, dynamic paramsObject)
|
||||||
|
{
|
||||||
|
return Task.Factory.StartNew<dynamic>(() =>
|
||||||
|
{
|
||||||
|
var method = methodTable[pluginName].Where(x => x.MethodName == methodName).FirstOrDefault();
|
||||||
|
var returnValue = method.Method.Invoke(method.Service, new object[] {paramsObject});
|
||||||
|
return returnValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task MakeNotif(string pluginName, string methodName, dynamic paramsObject)
|
||||||
|
{
|
||||||
|
return Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
var method = methodTable[pluginName].Where(x => x.MethodName == methodName).FirstOrDefault();
|
||||||
|
method.Method.Invoke(method.Service, paramsObject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,5 @@ namespace Zirconium.Core.Plugins.Interfaces
|
|||||||
void Initialize(IPluginHostAPI hostModuleAPI);
|
void Initialize(IPluginHostAPI hostModuleAPI);
|
||||||
void PreInitialize(IPluginManager pluginManager);
|
void PreInitialize(IPluginManager pluginManager);
|
||||||
string GetPluginUniqueName();
|
string GetPluginUniqueName();
|
||||||
dynamic GetExportedAPI();
|
|
||||||
Type[] GetExportedTypes();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using Zirconium.Core.Models;
|
using Zirconium.Core.Models;
|
||||||
|
|
||||||
namespace Zirconium.Core.Plugins.Interfaces
|
namespace Zirconium.Core.Plugins.Interfaces
|
||||||
@ -17,5 +18,8 @@ namespace Zirconium.Core.Plugins.Interfaces
|
|||||||
dynamic GetSettings(string pluginName);
|
dynamic GetSettings(string pluginName);
|
||||||
void ProvideAuth(IAuthProvider provider);
|
void ProvideAuth(IAuthProvider provider);
|
||||||
IExposedSessionManager GetSessionManager();
|
IExposedSessionManager GetSessionManager();
|
||||||
|
void RegisterIPCService(IPluginAPI plugin, dynamic service);
|
||||||
|
Task<dynamic> MakeIPCRequest(string pluginName, string methodName, dynamic paramsObject);
|
||||||
|
Task MakeIPCNotification(string pluginName, string methodName, dynamic paramsObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,6 @@ namespace Zirconium.Core.Plugins.Interfaces
|
|||||||
{
|
{
|
||||||
public interface IPluginManager
|
public interface IPluginManager
|
||||||
{
|
{
|
||||||
dynamic Depends(IPluginAPI currentPlugin, string pluginName);
|
void Depends(IPluginAPI currentPlugin, string pluginName);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,10 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Zirconium.Core.Models;
|
using Zirconium.Core.Models;
|
||||||
using Zirconium.Core.Plugins.Interfaces;
|
using Zirconium.Core.Plugins.Interfaces;
|
||||||
|
using Zirconium.Core.Plugins.IPC;
|
||||||
|
|
||||||
namespace Zirconium.Core.Plugins
|
namespace Zirconium.Core.Plugins
|
||||||
{
|
{
|
||||||
@ -9,11 +12,13 @@ namespace Zirconium.Core.Plugins
|
|||||||
{
|
{
|
||||||
private App _app;
|
private App _app;
|
||||||
private Router _router;
|
private Router _router;
|
||||||
|
private IPCRouter _ipcRouter;
|
||||||
|
|
||||||
public PluginHostAPI(App app, Router router)
|
public PluginHostAPI(App app, Router router)
|
||||||
{
|
{
|
||||||
_router = router;
|
_router = router;
|
||||||
_app = app;
|
_app = app;
|
||||||
|
_ipcRouter = new IPCRouter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExposedSessionManager GetSessionManager() {
|
public IExposedSessionManager GetSessionManager() {
|
||||||
@ -78,5 +83,18 @@ namespace Zirconium.Core.Plugins
|
|||||||
{
|
{
|
||||||
_router.RemoveCoreEventHandler(handler.GetHandlingEventType(), handler);
|
_router.RemoveCoreEventHandler(handler.GetHandlingEventType(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RegisterIPCService(IPluginAPI plugin, dynamic service)
|
||||||
|
{
|
||||||
|
_ipcRouter.RegisterIPCService(plugin.GetPluginUniqueName(), service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<dynamic> MakeIPCRequest(string pluginName, string methodName, dynamic paramsObject) {
|
||||||
|
return _ipcRouter.MakeRequest(pluginName, methodName, paramsObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task MakeIPCNotification(string pluginName, string methodName, dynamic paramsObject) {
|
||||||
|
return _ipcRouter.MakeNotif(pluginName, methodName, paramsObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ using McMaster.NETCore.Plugins;
|
|||||||
using Zirconium.Core.Logging;
|
using Zirconium.Core.Logging;
|
||||||
using Zirconium.Core.Models;
|
using Zirconium.Core.Models;
|
||||||
using Zirconium.Core.Plugins.Interfaces;
|
using Zirconium.Core.Plugins.Interfaces;
|
||||||
|
using Zirconium.Core.Plugins.IPC;
|
||||||
using Zirconium.Utils;
|
using Zirconium.Utils;
|
||||||
|
|
||||||
namespace Zirconium.Core.Plugins
|
namespace Zirconium.Core.Plugins
|
||||||
@ -73,7 +74,8 @@ namespace Zirconium.Core.Plugins
|
|||||||
typeof(IC2SMessageHandler),
|
typeof(IC2SMessageHandler),
|
||||||
typeof(ICoreEventHandler),
|
typeof(ICoreEventHandler),
|
||||||
typeof(BaseMessage),
|
typeof(BaseMessage),
|
||||||
typeof(CoreEvent)
|
typeof(CoreEvent),
|
||||||
|
typeof(ExportedIPCMethodAttribute)
|
||||||
},
|
},
|
||||||
config => config.PreferSharedTypes = true
|
config => config.PreferSharedTypes = true
|
||||||
);
|
);
|
||||||
@ -92,28 +94,18 @@ namespace Zirconium.Core.Plugins
|
|||||||
// This assumes the implementation of IPlugin has a parameterless constructor
|
// This assumes the implementation of IPlugin has a parameterless constructor
|
||||||
plugin = (IPluginAPI)Activator.CreateInstance(pluginType);
|
plugin = (IPluginAPI)Activator.CreateInstance(pluginType);
|
||||||
Logging.Log.Debug($"Created plugin instance '{plugin.GetPluginUniqueName()}'.");
|
Logging.Log.Debug($"Created plugin instance '{plugin.GetPluginUniqueName()}'.");
|
||||||
var exportedTypes = plugin.GetExportedTypes();
|
|
||||||
if (exportedTypes != null)
|
|
||||||
{
|
|
||||||
foreach (var type in exportedTypes)
|
|
||||||
{
|
|
||||||
var path = new Uri(type.Module.Assembly.CodeBase).LocalPath;
|
|
||||||
AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plugin.PreInitialize(this);
|
plugin.PreInitialize(this);
|
||||||
plugin.Initialize(_pluginHostAPI);
|
plugin.Initialize(_pluginHostAPI);
|
||||||
}
|
}
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public dynamic Depends(IPluginAPI currentPlugin, string pluginName)
|
public void Depends(IPluginAPI currentPlugin, string pluginName)
|
||||||
{
|
{
|
||||||
var dependantPlugin = _plugins.GetValueOrDefault(pluginName, null);
|
var dependantPlugin = _plugins.GetValueOrDefault(pluginName, null);
|
||||||
if (dependantPlugin != null) return dependantPlugin.GetExportedAPI();
|
if (dependantPlugin != null) return;
|
||||||
this.LoadPlugin(pluginName);
|
this.LoadPlugin(pluginName);
|
||||||
dependantPlugin = _plugins[pluginName];
|
dependantPlugin = _plugins[pluginName];
|
||||||
return dependantPlugin.GetExportedAPI();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,10 @@
|
|||||||
using System.Collections.Immutable;
|
using System;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Zirconium.Core.Plugins.Interfaces;
|
using Zirconium.Core.Plugins.Interfaces;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using Zirconium.Core.Logging;
|
using Zirconium.Core.Logging;
|
||||||
|
using Zirconium.Core.Plugins.IPC;
|
||||||
|
|
||||||
namespace MongoDBPlugin
|
namespace MongoDBPlugin
|
||||||
{
|
{
|
||||||
@ -10,18 +12,6 @@ namespace MongoDBPlugin
|
|||||||
{
|
{
|
||||||
private IMongoDatabase _database;
|
private IMongoDatabase _database;
|
||||||
|
|
||||||
public dynamic GetExportedAPI()
|
|
||||||
{
|
|
||||||
return _database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public System.Type[] GetExportedTypes()
|
|
||||||
{
|
|
||||||
// var mongoCore = Assembly.Load("MongoDB.Driver.Core");
|
|
||||||
// var mongoBson = Assembly.Load("MongoDB.Bson");
|
|
||||||
return new System.Type[] {typeof(IMongoDatabase)};
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPluginUniqueName()
|
public string GetPluginUniqueName()
|
||||||
{
|
{
|
||||||
return "MongoDB";
|
return "MongoDB";
|
||||||
@ -51,8 +41,25 @@ namespace MongoDBPlugin
|
|||||||
var db = client.GetDatabase(database);
|
var db = client.GetDatabase(database);
|
||||||
Log.Info("MongoDB is connected");
|
Log.Info("MongoDB is connected");
|
||||||
_database = db;
|
_database = db;
|
||||||
|
var ipcService = new IPCService(db);
|
||||||
|
pluginHostAPI.RegisterIPCService(this, ipcService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PreInitialize(IPluginManager pluginManager) { }
|
public void PreInitialize(IPluginManager pluginManager) { }
|
||||||
|
|
||||||
|
class IPCService
|
||||||
|
{
|
||||||
|
private IMongoDatabase _db;
|
||||||
|
|
||||||
|
public IPCService(IMongoDatabase db) { _db = db; }
|
||||||
|
|
||||||
|
[ExportedIPCMethod("Insert")]
|
||||||
|
public void Insert(dynamic paramsObject) {
|
||||||
|
var colName = paramsObject.ColName;
|
||||||
|
var model = paramsObject.Model;
|
||||||
|
_db.GetCollection<dynamic>(colName).InsertOne(model);
|
||||||
|
Log.Debug("successfully inserted the document");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,29 @@
|
|||||||
using Zirconium.Core.Plugins.Interfaces;
|
using System.Dynamic;
|
||||||
using MongoDB.Driver;
|
using Zirconium.Core.Plugins.Interfaces;
|
||||||
using Zirconium.Core.Logging;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace TestMongoDB
|
namespace TestMongoDB
|
||||||
{
|
{
|
||||||
class Plugin : IPluginAPI
|
class Plugin : IPluginAPI
|
||||||
{
|
{
|
||||||
private IMongoDatabase _database;
|
|
||||||
|
|
||||||
public dynamic GetExportedAPI()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type[] GetExportedTypes()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPluginUniqueName()
|
public string GetPluginUniqueName()
|
||||||
{
|
{
|
||||||
return "TestMongoDB";
|
return "TestMongoDB";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(IPluginHostAPI pluginHostAPI)
|
public async void Initialize(IPluginHostAPI pluginHostAPI)
|
||||||
{
|
{
|
||||||
var tm = new TestModel();
|
var tm = new TestModel();
|
||||||
tm.ABC = "qweqowie";
|
tm.ABC = "qweqowie";
|
||||||
_database.GetCollection<TestModel>("test_model").InsertOne(tm);
|
dynamic paramsObject = new ExpandoObject();
|
||||||
|
paramsObject.ColName = "test_model";
|
||||||
|
paramsObject.Model = tm;
|
||||||
|
await pluginHostAPI.MakeIPCRequest("MongoDB", "Insert", paramsObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PreInitialize(IPluginManager pluginManager)
|
public void PreInitialize(IPluginManager pluginManager)
|
||||||
{
|
{
|
||||||
var db = pluginManager.Depends(this, "MongoDB");
|
pluginManager.Depends(this, "MongoDB");
|
||||||
var receivedType = db.GetType();
|
|
||||||
Log.Debug(db.GetType().FullName);
|
|
||||||
Log.Debug(db.GetType().AssemblyQualifiedName);
|
|
||||||
foreach (Type i in db.GetType().GetInterfaces()) {
|
|
||||||
Log.Debug("DB object interface: " + i.AssemblyQualifiedName);
|
|
||||||
}
|
|
||||||
Log.Debug("Type info in current assembly context:");
|
|
||||||
var mongoDBType = typeof(IMongoDatabase);
|
|
||||||
Log.Debug(mongoDBType.FullName);
|
|
||||||
Log.Debug(mongoDBType.AssemblyQualifiedName);
|
|
||||||
Log.Debug(new Uri(mongoDBType.Module.Assembly.CodeBase).LocalPath);
|
|
||||||
Log.Debug($"Casting compatibility: {mongoDBType.IsAssignableFrom(db.GetType())}");
|
|
||||||
_database = (IMongoDatabase) db;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
<ProjectReference Include="../../Zirconium/Zirconium.csproj">
|
<ProjectReference Include="../../Zirconium/Zirconium.csproj">
|
||||||
<ExcludeAssets>runtime</ExcludeAssets>
|
<ExcludeAssets>runtime</ExcludeAssets>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="../MongoDB/MongoDB.csproj"/>
|
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user