0

I have a main project that uses a plugin architecture. The main project cannot know about the plugins. For this, I am using https://web.archive.org/web/20170506195518/http://www.squarewidget.com:80/pluggable-architecture-in-asp.net-mvc-4

While I don't fully understand what this is doing, it does work for me.

What I need to do now is to call a method in an unrelated DLL. I have an example method...

namespace MyPlugins.Controllers
{
    public class Calculate
    {
        public float Add(float a, float b)
        {
            return a + b;
        }
    }
}

I want to call it, by only knowing its name (as a string), such like...

    string MethodToCall = "MyPlugins.Controllers.Calculate.Add";
    float a = 12.7F;
    float ab = 123F;

    dynamic result = CallMethod(MethodToCall, new object[] { a, ab });

For this, I have looked and tried various methods, but none of them are working for me. Here is my current CallMethod.

public dynamic CallMethod(string Method, object[] Params = null)
{
    string[] MethodPath = Method.Split('.');

    try
    {
        string MethodType = MethodPath[0];

        if (MethodPath.Length > 2)
        {
            for (int i = 1; i < MethodPath.Length - 1; i++)
            {
                MethodType += "." + MethodPath[i];
            }
        }
        Type t = Type.GetType(MethodType);

        Type[] myObjects = new Type[Params.Count()];

        for (int i = 0; i < Params.Length; i++)
        {
            myObjects[i] = Type.GetType(Params[i].GetType().FullName);
        }

        var methodInfo = t.GetMethod(MethodPath[MethodPath.Length - 1], myObjects);
        if (methodInfo == null)
        {
            // never throw generic Exception - replace this with some other exception type
            throw new Exception("No such method exists.");
        }

        var o = Activator.CreateInstance(t);

        object[] parameters = new object[Params.Length];

        for (int i = 0; i < Params.Length; i++)
        {
            parameters[i] = Params[i];
        }

        var r = methodInfo.Invoke(o, parameters);

        return r;
    }
    catch
    {
        return null;
    }
}

The problem I am seeing is that the Type.GetType(MethodType) always returns null.

My thoughts are that as I am using the SquareWidget example (link above), is that the assembly is loaded so should just be able to call it.

Thank you for your help.

David
  • 214
  • 3
  • 15
  • Why do you want to call a method in an unrelated dll? Tell us more about the requirements rather than what solution you think is the correct one. It looks like you want to call the `Add` method in your plugin library, the question is, why? Is every plugin going to have this add method? How does your main program know what the surface area of the plug-in looks like? – Charleh Feb 14 '21 at 12:37
  • I have JSON coming in and need to be able to handle it. Each JSON file could be a different type of data, so when I handle it, I need to be more specific on how it is handled. The Add method is just a snippet I used to test. Each JSON will have the method I need to call in order for me to handle it, so at this point, I do not know which DLL or method I need to call. This JSON could change at any time. – David Feb 14 '21 at 12:48
  • Are the methods pre defined or could a plug-in implement a method that has never been seen before by any other plugin? If the former you can use interfaces, otherwise you may need to make calls using reflection as you've already found. – Charleh Feb 14 '21 at 14:25
  • A plugin could implement a method not seen before. I could create a new set of JSON data and the add a new plugin to handle that. The idea being I drop the plugin into my bin folder, without changing anything in the host project. – David Feb 14 '21 at 18:58
  • You don't necessarily need to call methods dynamically then, if your JSON identifies which plugin handles it, all you need to do is ask each plugin if it can handle the given JSON via an interface method, then if it can handle the JSON pass it on a processing method. I'm assuming a lot but generally you can avoid reflection using interfaces in a plug-in architecture, but it really does depend on the use case. – Charleh Feb 14 '21 at 20:06
  • I've never really used interfaces, so I don't really understand (yet) how I would approach this. Yes, my JSON will identify which plugin it requires, but... the host system that is currently handling the JSON cannot at this point know anything about the plugin. (The plugin is OK to know about the host, but not the other way around) – David Feb 14 '21 at 20:17
  • Read up on interfaces, you can basically have the plug-in implement an interface that the main application provides. The application won't know anything about the plug-in apart from that there are one or more *things* implementing the interface (it doesn't need to know any specifics about the plug-in). The interface then becomes the contract that your main app expects the plugins to abide by, the plugins themselves are free to implement their functionality how they see fit. The plug-in needs to reference the main app library (or at least a plugin library that provides the interface definition) – Charleh Feb 14 '21 at 21:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228734/discussion-between-david-and-charleh). – David Feb 15 '21 at 10:54

0 Answers0