enhance script plugin features
(support service resolver with generic args) (support requiresTarget for command)
This commit is contained in:
parent
70cae976a0
commit
7f11921757
@ -25,7 +25,7 @@ namespace IW4MAdmin.Application.Factories
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction)
|
public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, bool isTargetRequired, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction)
|
||||||
{
|
{
|
||||||
var permissionEnum = Enum.Parse<Permission>(permission);
|
var permissionEnum = Enum.Parse<Permission>(permission);
|
||||||
var argsArray = args.Select(_arg => new CommandArgument
|
var argsArray = args.Select(_arg => new CommandArgument
|
||||||
@ -34,7 +34,7 @@ namespace IW4MAdmin.Application.Factories
|
|||||||
Required = _arg.Item2
|
Required = _arg.Item2
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
return new ScriptCommand(name, alias, description, permissionEnum, argsArray, executeAction, _config, _transLookup);
|
return new ScriptCommand(name, alias, description, isTargetRequired, permissionEnum, argsArray, executeAction, _config, _transLookup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
{
|
{
|
||||||
private readonly Action<GameEvent> _executeAction;
|
private readonly Action<GameEvent> _executeAction;
|
||||||
|
|
||||||
public ScriptCommand(string name, string alias, string description, Permission permission,
|
public ScriptCommand(string name, string alias, string description, bool isTargetRequired, Permission permission,
|
||||||
CommandArgument[] args, Action<GameEvent> executeAction, CommandConfiguration config, ITranslationLookup layout)
|
CommandArgument[] args, Action<GameEvent> executeAction, CommandConfiguration config, ITranslationLookup layout)
|
||||||
: base(config, layout)
|
: base(config, layout)
|
||||||
{
|
{
|
||||||
@ -24,6 +24,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
Name = name;
|
Name = name;
|
||||||
Alias = alias;
|
Alias = alias;
|
||||||
Description = description;
|
Description = description;
|
||||||
|
RequiresTarget = isTargetRequired;
|
||||||
Permission = permission;
|
Permission = permission;
|
||||||
Arguments = args;
|
Arguments = args;
|
||||||
}
|
}
|
||||||
|
@ -252,6 +252,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
string alias = dynamicCommand.alias;
|
string alias = dynamicCommand.alias;
|
||||||
string description = dynamicCommand.description;
|
string description = dynamicCommand.description;
|
||||||
string permission = dynamicCommand.permission;
|
string permission = dynamicCommand.permission;
|
||||||
|
bool targetRequired = false;
|
||||||
|
|
||||||
List<(string, bool)> args = new List<(string, bool)>();
|
List<(string, bool)> args = new List<(string, bool)>();
|
||||||
dynamic arguments = null;
|
dynamic arguments = null;
|
||||||
@ -266,6 +267,16 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
// arguments are optional
|
// arguments are optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
targetRequired = dynamicCommand.targetRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (RuntimeBinderException)
|
||||||
|
{
|
||||||
|
// arguments are optional
|
||||||
|
}
|
||||||
|
|
||||||
if (arguments != null)
|
if (arguments != null)
|
||||||
{
|
{
|
||||||
foreach (var arg in dynamicCommand.arguments)
|
foreach (var arg in dynamicCommand.arguments)
|
||||||
@ -290,7 +301,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commandList.Add(scriptCommandFactory.CreateScriptCommand(name, alias, description, permission, args, execute));
|
commandList.Add(scriptCommandFactory.CreateScriptCommand(name, alias, description, permission, targetRequired, args, execute));
|
||||||
}
|
}
|
||||||
|
|
||||||
return commandList;
|
return commandList;
|
||||||
|
@ -18,14 +18,31 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
|
|
||||||
public object ResolveService(string serviceName)
|
public object ResolveService(string serviceName)
|
||||||
{
|
{
|
||||||
var serviceType = typeof(IScriptPluginServiceResolver).Assembly.GetTypes().FirstOrDefault(_type => _type.Name == serviceName);
|
var serviceType = DetermineRootType(serviceName);
|
||||||
|
return _serviceProvider.GetService(serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ResolveService(string serviceName, string[] genericParameters)
|
||||||
|
{
|
||||||
|
var serviceType = DetermineRootType(serviceName, genericParameters.Length);
|
||||||
|
var genericTypes = genericParameters.Select(_genericTypeParam => DetermineRootType(_genericTypeParam));
|
||||||
|
var resolvedServiceType = serviceType.MakeGenericType(genericTypes.ToArray());
|
||||||
|
return _serviceProvider.GetService(resolvedServiceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type DetermineRootType(string serviceName, int genericParamCount = 0)
|
||||||
|
{
|
||||||
|
var typeCollection = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(t => t.GetTypes());
|
||||||
|
string generatedName = $"{serviceName}{(genericParamCount == 0 ? "" : $"`{genericParamCount}")}".ToLower();
|
||||||
|
var serviceType = typeCollection.FirstOrDefault(_type => _type.Name.ToLower() == generatedName);
|
||||||
|
|
||||||
if (serviceType == null)
|
if (serviceType == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"No service type '{serviceName}' defined in IW4MAdmin assembly");
|
throw new InvalidOperationException($"No object type '{serviceName}' defined in loaded assemblies");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _serviceProvider.GetService(serviceType);
|
return serviceType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ let commands = [{
|
|||||||
alias: "pp",
|
alias: "pp",
|
||||||
// required
|
// required
|
||||||
permission: "User",
|
permission: "User",
|
||||||
|
// optional (defaults to false)
|
||||||
|
targetRequired: false,
|
||||||
// optional
|
// optional
|
||||||
arguments: [{
|
arguments: [{
|
||||||
name: "times to ping",
|
name: "times to ping",
|
||||||
|
@ -15,9 +15,10 @@ namespace SharedLibraryCore.Interfaces
|
|||||||
/// <param name="alias">alias of command</param>
|
/// <param name="alias">alias of command</param>
|
||||||
/// <param name="description">description of command</param>
|
/// <param name="description">description of command</param>
|
||||||
/// <param name="permission">minimum required permission</param>
|
/// <param name="permission">minimum required permission</param>
|
||||||
|
/// <param name="isTargetRequired">target required or not</param>
|
||||||
/// <param name="args">command arguments (name, is required)</param>
|
/// <param name="args">command arguments (name, is required)</param>
|
||||||
/// <param name="executeAction">action to peform when commmand is executed</param>
|
/// <param name="executeAction">action to peform when commmand is executed</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction);
|
IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, bool isTargetRequired, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,25 @@
|
|||||||
namespace SharedLibraryCore.Interfaces
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Interfaces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// interface used to dynamically resolve services by string name
|
/// interface used to dynamically resolve services by string name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IScriptPluginServiceResolver
|
public interface IScriptPluginServiceResolver
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// resolves a service with the given name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceName">class name of service</param>
|
||||||
|
/// <returns></returns>
|
||||||
object ResolveService(string serviceName);
|
object ResolveService(string serviceName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// resolves a service with the given name and generic params
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceName">class name of service</param>
|
||||||
|
/// <param name="genericParams">generic class names</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
object ResolveService(string serviceName, string[] genericParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
Tests/ApplicationTests/Mocks/ScriptResolverGenericMock.cs
Normal file
23
Tests/ApplicationTests/Mocks/ScriptResolverGenericMock.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
namespace ApplicationTests.Mocks
|
||||||
|
{
|
||||||
|
public interface IScriptResolverMock
|
||||||
|
{
|
||||||
|
string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScriptResolverMock : IScriptResolverMock
|
||||||
|
{
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
public interface IScriptResolverGenericMock<T, V>
|
||||||
|
{
|
||||||
|
T Value { get; set; }
|
||||||
|
V Value2 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScriptResolverGenericMock<T, V> : IScriptResolverGenericMock<T, V>
|
||||||
|
{
|
||||||
|
public T Value { get; set; }
|
||||||
|
public V Value2 { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,7 @@ namespace ApplicationTests
|
|||||||
serviceProvider = new ServiceCollection().BuildBase()
|
serviceProvider = new ServiceCollection().BuildBase()
|
||||||
.AddSingleton(A.Fake<ClientService>())
|
.AddSingleton(A.Fake<ClientService>())
|
||||||
.AddSingleton<IScriptCommandFactory, ScriptCommandFactory>()
|
.AddSingleton<IScriptCommandFactory, ScriptCommandFactory>()
|
||||||
|
.AddSingleton(A.Fake<IScriptPluginServiceResolver>())
|
||||||
.BuildServiceProvider();
|
.BuildServiceProvider();
|
||||||
fakeManager = serviceProvider.GetRequiredService<IManager>();
|
fakeManager = serviceProvider.GetRequiredService<IManager>();
|
||||||
mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
|
mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
|
||||||
@ -66,7 +67,7 @@ namespace ApplicationTests
|
|||||||
A.CallTo(() => fakeManager.GetClientService())
|
A.CallTo(() => fakeManager.GetClientService())
|
||||||
.Returns(fakeClientService);
|
.Returns(fakeClientService);
|
||||||
|
|
||||||
await plugin.Initialize(serviceProvider.GetRequiredService<IManager>(), serviceProvider.GetRequiredService<IScriptCommandFactory>());
|
await plugin.Initialize(serviceProvider.GetRequiredService<IManager>(), serviceProvider.GetRequiredService<IScriptCommandFactory>(), serviceProvider.GetRequiredService<IScriptPluginServiceResolver>());
|
||||||
|
|
||||||
var gameEvent = new GameEvent()
|
var gameEvent = new GameEvent()
|
||||||
{
|
{
|
||||||
|
66
Tests/ApplicationTests/ScriptPluginServiceResolverTests.cs
Normal file
66
Tests/ApplicationTests/ScriptPluginServiceResolverTests.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using ApplicationTests.Mocks;
|
||||||
|
using IW4MAdmin.Application.Misc;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ApplicationTests
|
||||||
|
{
|
||||||
|
public class ScriptPluginServiceResolverTests
|
||||||
|
{
|
||||||
|
private IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
serviceProvider = new ServiceCollection()
|
||||||
|
.BuildBase()
|
||||||
|
.AddSingleton<ScriptPluginServiceResolver>()
|
||||||
|
.AddSingleton<IScriptResolverMock, ScriptResolverMock>()
|
||||||
|
.AddSingleton(new ScriptResolverMock { Value = "test" })
|
||||||
|
.AddSingleton<IScriptResolverGenericMock<int, string>, ScriptResolverGenericMock<int,string>>()
|
||||||
|
.AddSingleton(new ScriptResolverGenericMock<int, string> { Value = 123, Value2 = "test" })
|
||||||
|
.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_ResolveType()
|
||||||
|
{
|
||||||
|
var resolver = serviceProvider.GetService<ScriptPluginServiceResolver>();
|
||||||
|
var expectedResolvedService = serviceProvider.GetService<ScriptResolverMock>();
|
||||||
|
var resolvedService = resolver.ResolveService(nameof(ScriptResolverMock));
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedResolvedService, resolvedService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_ResolveType_Interface()
|
||||||
|
{
|
||||||
|
var resolver = serviceProvider.GetService<ScriptPluginServiceResolver>();
|
||||||
|
var expectedResolvedService = serviceProvider.GetService<IScriptResolverMock>();
|
||||||
|
var resolvedService = resolver.ResolveService(nameof(IScriptResolverMock));
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedResolvedService, resolvedService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_ResolveGenericType()
|
||||||
|
{
|
||||||
|
var resolver = serviceProvider.GetService<ScriptPluginServiceResolver>();
|
||||||
|
var expectedResolvedService = serviceProvider.GetService<ScriptResolverGenericMock<int, string>>();
|
||||||
|
var resolvedService = resolver.ResolveService("ScriptResolverGenericMock", new[] { "Int32", "String" });
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedResolvedService, resolvedService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_ResolveGenericType_Interface()
|
||||||
|
{
|
||||||
|
var resolver = serviceProvider.GetService<ScriptPluginServiceResolver>();
|
||||||
|
var expectedResolvedService = serviceProvider.GetService<IScriptResolverGenericMock<int, string>>();
|
||||||
|
var resolvedService = resolver.ResolveService("IScriptResolverGenericMock", new[] { "Int32", "String" });
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedResolvedService, resolvedService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user