How to reference a DLL on runtime?

后端 未结 6 953
有刺的猬
有刺的猬 2020-12-08 23:43

I\'m building an application with WPF and C#, basically I want to allow anyone to create a dll and put it into a folder (similar to plugins). The application will take all t

相关标签:
6条回答
  • 2020-12-09 00:13

    Have a look at MEF. it should provide exactly what you are looking for.

    Using reflection is also an option, but MEF will be a better choice if you ask me.

    0 讨论(0)
  • 2020-12-09 00:18

    I am working on something similar, where a customer may have different versions of a third-party DLL installed, though the name and location are the same. If we don't reference the right version, we get failures. I am using reflection to identify the version, but I need to either modify the setup to use a different DAL class depending on the version, or make the DAL version independent through an interface.

    I am leaning toward the second. If you make a "dummy DLL in your code that implements an interface that has all the methods you want to invoke from the target assembly, and pass in not the actual type as a parameter but the interface, then you should be able to use all the methods in your design-time code and compile based on your mock-up implementations, and even do your testing, but then when you load the actual assembly at runtime get the results from the real assembly. Let me know if this works for you, and I will let you know as well.

    Joey Morgan

    0 讨论(0)
  • 2020-12-09 00:25

    I think you can start of with something like

    Assembly assembly = Assembly.LoadFrom("Something.dll");
    Type type = assembly.GetType("SomeType");
    object instanceOfSomeType = Activator.CreateInstance(type);
    

    Then you can use it

    0 讨论(0)
  • 2020-12-09 00:25

    The answers above pretty much give you what you need. You can try to load all dlls to be plugged into your app when the program starts up:

    // note: your path may differ, this one assumes plugins directory where exe is executed
    var pluginsDirectory = Path.Combine(AppContext.BaseDirectory, "plugins");
    if (Directory.Exists(pluginsDirectory))
    {
        var dllPaths = Directory.GetFiles(pluginsDirectory);
        if (dllPaths.Count() > 0)
        {
            foreach (var dllPath in dllPaths)
            {
                Assembly.LoadFrom(Path.Combine("plugins", Path.GetFileName(dllPath)));
            }
        }
        else
        {
            // warn about no dlls
        }
    }
    else
    {
        // warn about no plugins directory
    }
    

    How to reference the dll and its types:

    // if dll file name is My.Plugin.Assembly.ShortName.dll, then reference as follows
    var pluginAssembly = Assembly.Load("My.Plugin.Assembly.ShortName");
    var typesInAssembly = pluginAssembly.GetExportedTypes();
    var instanceType = typesInAssembly.FirstOrDefault(t => t.Name == "MyClassName");
    var instance = Activator.CreateInstance(instanceType, new object[] { "constructorParam1", "constructorParam2" });
    instanceType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, instance, new object[] { "methodParam1", "methodParam2" });
    

    You may need to tell your app configuration to probe your plugins directory. I'm assuming one child directory of plugins, you can probe a list of subdirectory paths.

    ...
    <runtime>
        <assemblyBinding ...
            <probing privatePath="plugins" />
    ...
    

    You will need something to tell you which type to implement (perhaps configuration mapping). The interface, as best I can tell, will just provide a contract all the plugins implement to provide an expected method to invoke via reflection.

    0 讨论(0)
  • 2020-12-09 00:29

    I've implemented something like you are asking for that searches through dlls in a given directory and finds classes that implement a particular interface. Below is the class I used to do this:

    public class PlugInFactory<T>
    {
        public T CreatePlugin(string path)
        {
            foreach (string file in Directory.GetFiles(path, "*.dll"))
            {
                foreach (Type assemblyType in Assembly.LoadFrom(file).GetTypes())
                {
                    Type interfaceType = assemblyType.GetInterface(typeof(T).FullName);
    
                    if (interfaceType != null)
                    {
                        return (T)Activator.CreateInstance(assemblyType);
                    }
                }
            }
    
            return default(T);
        }
    }
    

    All you have to do is initialize this class with something like this:


       PlugInFactory<InterfaceToSearchFor> loader = new PlugInFactory<InterfaceToSearchFor>();
         InterfaceToSearchFor instanceOfInterface = loader.CreatePlugin(AppDomain.CurrentDomain.BaseDirectory);
    

    If this answer or any of the other answers help you in solving your problem please mark it as the answer by clicking the checkmark. Also if you feel like it's a good solution upvote it to show your appreciation. Just thought I'd mention it since it doesn't look like you accepted answers on any of your other questions.

    0 讨论(0)
  • 2020-12-09 00:30
      string relative = "ClassLibrary1.dll";
                string absolute = Path.GetFullPath(relative);
    
                Assembly assembly = Assembly.LoadFile(absolute);
                System.Type assemblytype = assembly.GetType("ClassLibrary1.Class1");
                 object []argtoppass={1,2};
              var a =Activator.CreateInstance(assemblytype, argtoppass);
              System.Type type = a.GetType();
              if (type != null)
              {
                  string methodName = "add";
                  MethodInfo methodInfo = type.GetMethod(methodName);
                  object   result = methodInfo.Invoke(a, null);
    
                  int a1 = (int )result;
              }
    
    0 讨论(0)
提交回复
热议问题