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/>
|
||||
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 argsArray = args.Select(_arg => new CommandArgument
|
||||
@ -34,7 +34,7 @@ namespace IW4MAdmin.Application.Factories
|
||||
Required = _arg.Item2
|
||||
}).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;
|
||||
|
||||
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)
|
||||
: base(config, layout)
|
||||
{
|
||||
@ -24,6 +24,7 @@ namespace IW4MAdmin.Application.Misc
|
||||
Name = name;
|
||||
Alias = alias;
|
||||
Description = description;
|
||||
RequiresTarget = isTargetRequired;
|
||||
Permission = permission;
|
||||
Arguments = args;
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ namespace IW4MAdmin.Application.Misc
|
||||
string alias = dynamicCommand.alias;
|
||||
string description = dynamicCommand.description;
|
||||
string permission = dynamicCommand.permission;
|
||||
bool targetRequired = false;
|
||||
|
||||
List<(string, bool)> args = new List<(string, bool)>();
|
||||
dynamic arguments = null;
|
||||
@ -266,6 +267,16 @@ namespace IW4MAdmin.Application.Misc
|
||||
// arguments are optional
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
targetRequired = dynamicCommand.targetRequired;
|
||||
}
|
||||
|
||||
catch (RuntimeBinderException)
|
||||
{
|
||||
// arguments are optional
|
||||
}
|
||||
|
||||
if (arguments != null)
|
||||
{
|
||||
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;
|
||||
|
@ -18,14 +18,31 @@ namespace IW4MAdmin.Application.Misc
|
||||
|
||||
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)
|
||||
{
|
||||
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",
|
||||
// required
|
||||
permission: "User",
|
||||
// optional (defaults to false)
|
||||
targetRequired: false,
|
||||
// optional
|
||||
arguments: [{
|
||||
name: "times to ping",
|
||||
|
@ -15,9 +15,10 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// <param name="alias">alias of command</param>
|
||||
/// <param name="description">description of command</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="executeAction">action to peform when commmand is executed</param>
|
||||
/// <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>
|
||||
/// interface used to dynamically resolve services by string name
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
/// <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()
|
||||
.AddSingleton(A.Fake<ClientService>())
|
||||
.AddSingleton<IScriptCommandFactory, ScriptCommandFactory>()
|
||||
.AddSingleton(A.Fake<IScriptPluginServiceResolver>())
|
||||
.BuildServiceProvider();
|
||||
fakeManager = serviceProvider.GetRequiredService<IManager>();
|
||||
mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
|
||||
@ -66,7 +67,7 @@ namespace ApplicationTests
|
||||
A.CallTo(() => fakeManager.GetClientService())
|
||||
.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()
|
||||
{
|
||||
|
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