• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

luttje / Key2Joy / 6517266969

14 Oct 2023 11:05AM UTC coverage: 12.469% (+0.2%) from 12.308%
6517266969

push

github

web-flow
Implementing plugins for better separation (#39)

* Start implementing plugins for better separation
* massive refactor in attempt to split appdomains for plugins
* (breaks old mapping profiles)
* Fix error when switching from mouse button trigger to keyboard trigger and clicking in the combobox where the mouse button capture textbox is.
* Simplify code by removing legacy
* SImplify grouping actions
* Fix profile and add helpful opposite mapping generator tool
* Change solution hierarchy
* Restrict AppDomain plugins went from Zone.MyComputer -> .Internet
* create keypair in ci
* Install the .NET framework tools
* Run command in workflow
* Plugin permissions. Plugins disabled by default
* update readme (icon is no longer used)
* Plugin action runs in seperated process
* Remove unused dependencies.
* Fix action name display for mapping
* Fix Lua plugin script calls (NOTE: laggy when using MessageBox)
* convert project to sdk style
* Add editorconfig and start cleaning up
* Fix documentation. Update namespaces to match files (breaks profiles)
* Include all projects in tests, disable building docs on debug
* Add messagebox script action
* Add tests for pluginhost
* Remove administrator from window title test
* add some icons to ui
* Add enabling/disabling plugins
* Close plugins when Key2Joy shuts down
* Fix appcommand failing
* Fix plugin permission form crashing. Fix plugin load exception not showing warning
* Handle plugin host closing better when app has crashed
* Seperate host and client logic in remote event subscriber
* Ensure the PluginHost shuts down if the app crashes
* Better error output for plugins
* Fix cmd interop not working, add some tests
* also generate docs on plugins
* Fix build order with docs
* Fix enum script parameters and ensure actions share environment scopes
* Fix _wpftmp folders being created dotnet/wpf#2930
* Fix sequence action. Add disabled trigger/action for unloaded plugins on start... (continued)

180 of 1703 branches covered (0.0%)

Branch coverage included in aggregate %.

6419 of 6419 new or added lines in 207 files covered. (100.0%)

1035 of 8041 relevant lines covered (12.87%)

8445.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.94
/Core/Key2Joy.Core/Plugins/ExposedMethod.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Reflection;
5
using System.Runtime.Serialization;
6
using Key2Joy.Util;
7

8
namespace Key2Joy.Plugins;
9

10
public delegate object ParameterTransformerDelegate(object parameter, Type methodParameterType);
11

12
public delegate object ParameterTransformerDelegate<T>(T parameter, Type methodParameterType);
13

14
public abstract class ExposedMethod
15
{
16
    public string FunctionName { get; protected set; }
58✔
17
    public string MethodName { get; protected set; }
58✔
18

19
    protected object Instance { get; private set; }
29✔
20

21
    private readonly Dictionary<Type, ParameterTransformerDelegate> parameterTransformers = new();
29✔
22
    protected IList<Type> ParameterTypes { get; private set; } = new List<Type>();
58✔
23

24
    public ExposedMethod(string functionName, string methodName)
29✔
25
    {
29✔
26
        this.FunctionName = functionName;
29✔
27
        this.MethodName = methodName;
29✔
28
    }
29✔
29

30
    public void Prepare(object instance)
31
    {
29✔
32
        this.Instance = instance;
29✔
33
        this.ParameterTypes = this.GetParameterTypes();
29✔
34
    }
29✔
35

36
    public abstract IList<Type> GetParameterTypes();
37

38
    public abstract object InvokeMethod(object[] transformedParameters);
39

40
    /// <summary>
41
    /// Register a transformer for certain types coming from scripts.
42
    /// The transformer will get the parameter value and the type of the method parameter.
43
    /// The transformer must return an object that will be passed to the method.
44
    /// </summary>
45
    /// <typeparam name="T"></typeparam>
46
    /// <param name="transformer"></param>
47
    public void RegisterParameterTransformer<T>(ParameterTransformerDelegate<T> transformer)
48
    {
58✔
49
        var key = typeof(T);
58✔
50

51
        if (this.parameterTransformers.ContainsKey(key))
58!
52
        {
×
53
            this.parameterTransformers.Remove(key);
×
54
        }
×
55

56
        this.parameterTransformers.Add(key, (p, t) => transformer((T)p, t));
58✔
57
    }
58✔
58

59
    /// <summary>
60
    /// Will try to transform the parameter to the type of the method parameter.
61
    /// </summary>
62
    /// <param name="parameters"></param>
63
    /// <returns></returns>
64
    /// <exception cref="NotImplementedException"></exception>
65
    public object TransformAndRedirect(params object[] parameters)
66
    {
×
67
        var transformedParameters = parameters.Select((parameter, parameterIndex) =>
×
68
        {
×
69
            var parameterType = this.ParameterTypes[parameterIndex];
×
70

×
71
            if (this.parameterTransformers.TryGetValue(parameter.GetType(), out var transformer))
×
72
            {
×
73
                return transformer(parameter, parameterType);
×
74
            }
×
75

×
76
            // If the parameter type is an enumeration, we try to convert the parameter to the enum value.
×
77
            if (parameterType.IsEnum)
×
78
            {
×
79
                return Enum.Parse(parameterType, parameter.ToString());
×
80
            }
×
81

×
82
            if (parameter is object[] objectArrayParameter && parameterType.IsArray)
×
83
            {
×
84
                // TODO: This breaks the reference to the original array
×
85
                // TODO: Inform plugin creators that if they want to keep the original reference, they should
×
86
                //       use the 'object' type and cast the array to the correct type themselves.
×
87
                parameter = objectArrayParameter.CopyArrayToNewType(parameterType.GetElementType());
×
88
            }
×
89

×
90
            if (parameter is MarshalByRefObject or ISerializable)
×
91
            {
×
92
                return parameter;
×
93
            }
×
94

×
95
            if (parameter.GetType().IsSerializable)
×
96
            {
×
97
                return parameter;
×
98
            }
×
99

×
100
            throw new NotImplementedException("Parameter type not supported as an exposed method parameter: " + parameter.GetType().FullName);
×
101
        }).ToArray();
×
102

103
        return this.InvokeMethod(transformedParameters);
×
104
    }
×
105

106
    /// <summary>
107
    /// MethodInfo that can be bound to scripts
108
    /// </summary>
109
    /// <returns></returns>
110
    public virtual MethodInfo GetExecutorMethodInfo() => typeof(ExposedMethod).GetMethod(nameof(TransformAndRedirect));
29✔
111
}
112

113
public class TypeExposedMethod : ExposedMethod
114
{
115
    public Type Type { get; protected set; }
58✔
116

117
    private readonly MethodInfo cachedMethodInfo;
118

119
    public TypeExposedMethod(string functionName, string methodName, Type type)
120
        : base(functionName, methodName)
29✔
121
    {
29✔
122
        this.Type = type;
29✔
123
        this.cachedMethodInfo = this.Type.GetMethod(this.MethodName);
29✔
124
    }
29✔
125

126
    public override IList<Type> GetParameterTypes()
127
        => this.cachedMethodInfo.GetParameters().Select(p => p.ParameterType).ToList();
78✔
128

129
    public override object InvokeMethod(object[] transformedParameters)
130
        => this.cachedMethodInfo.Invoke(this.Instance, transformedParameters);
×
131
}
132

133
public class PluginExposedMethod : ExposedMethod
134
{
135
    public string TypeName { get; protected set; }
×
136

137
    private readonly PluginHostProxy pluginHost;
138

139
    public PluginExposedMethod(PluginHostProxy pluginHost, string typeName, string functionName, string methodName)
140
        : base(functionName, methodName)
×
141
    {
×
142
        this.pluginHost = pluginHost;
×
143
        this.TypeName = typeName;
×
144
    }
×
145

146
    public override IList<Type> GetParameterTypes()
147
    {
×
148
        var instance = (PluginActionProxy)this.Instance;
×
149
        return instance.GetMethodParameterTypes(this.MethodName);
×
150
    }
×
151

152
    public override object InvokeMethod(object[] transformedParameters)
153
    {
×
154
        var instance = (PluginActionProxy)this.Instance;
×
155
        return instance.InvokeScriptMethod(this.MethodName, transformedParameters);
×
156
    }
×
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc