0

Are there any patterns that address how to have and application load and run user defined code at run-time? I am looking into developing a C# library that the users of a Test Executive application (app that interacts with HW to test mobile devices in development) can leverage to define test code (currently the tests are defined in xml through a rather cumbersome/poorly designed UI and we have had requests for some sort of library). The test code will need to be loaded and run by the application. The proposed approach is...

  1. Distribute Library of methods that a user can develop tests with
  2. Distribute a small framework with interfaces that should be implemented so that the application can locate test code.
  3. User compiles tests into DLLs from project that references DLLs from 1 and 2
  4. Application loads user supplied DLLs (generated in step 3) and locates test method (defined in framework from 2) via reflection on the DLL
  5. Application runs test code which should be a series of method calls from 1
  6. The library from 1 uses reflection so that each method call from the library maps to some series of calls defined within the running application assembly.

The user might write something that looks like this:

using MyFramework;
using MyLib;
namespace Test
{
    public class MyTest : MyFramework.Test //defines the abstract RunTest method
    {
      public override void RunTest() { //user implements RunTest
        //the test code
        MyLib.Commands commands = new MyLib.Commands();
        commands.Command1();
        commands.Command2();
      }
    }
}

The code that the user writes will be compiled to a DLL and made available to the application. MyLib.Commands.Command1 would do this (illustration of point number 6):

public void Command1() {
    Assembly exeAssembly = Assembly.LoadFile(@"C:\theAppThatRunsTheUserCode.exe");
    Type typeInAppWhereLibCallsMapTo = exeAssembly.GetType("app.targetType");
    MethodInfo methodMappedToLibCall = typeInAppWhereLibCallsMapTo.GetMethod("AppCommand1");
    methodMappedToLibCall.Invoke(null, null);  
}

The application would run user-code like this:

public void RunTheUserTest() {
    Assembly dllAssembly = Assembly.LoadFile(@"C:\Test.dll");
    Type testType = dllAssembly.GetType("Test.MyTest");
    object myTestInstance = Activator.CreateInstance(testType);
    MethodInfo runTestMethodInfo = testType.GetMethod("RunTest");
    runTestMethodInfo.Invoke(myTestInstance, null);
}

Are there any well known design patterns that are better suited to solve this type of problem? I'm wondering if this is an okay approach. If not, what's wrong with it? Are there easier/"more elegant" ways to solve this type of problem?

  • 2
    Are you sure you aren't reinventing the wheel? There are test runners that do this already, and they come with a lot of tools. – John Wu Jul 31 '18 at 22:31
  • @Jo So your answer is "yes there are easier ways to solve this problem?" – Doug Tait Jul 31 '18 at 22:37
  • IDK Doug, I don't know if you looked at existing test runners and ruled them out for some reason, which is why I bring it up. – John Wu Jul 31 '18 at 23:37
1

The Managed Extensibility Framework (MEF) can handle the wiring of classes from .dll files loaded at runtime according to some shared interface definition.

Basically speaking, you declare a dependency by adding the [Import] attribute. This dependency will be fullfilled with whatever can be found in the loaded .dll files that has a matching [Export] attribute.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.