如何在运行时引用DLL
本文关键字:引用 DLL 运行时 | 更新日期: 2023-09-27 17:52:36
我正在用WPF和c#构建一个应用程序,基本上我想允许任何人创建一个dll并将其放入文件夹(类似于插件)。应用程序将获取文件夹中的所有dll,加载它们并使用它们的方法(在接口上定义)。
你知道如何在运行时引用dll吗?有更好的主意如何实现这一点吗?
我已经实现了像您所要求的那样,在给定目录中搜索dll并查找实现特定接口的类。下面是我用来做这件事的类:
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);
}
}
你所要做的就是像这样初始化这个类:
PlugInFactory<InterfaceToSearchFor> loader = new PlugInFactory<InterfaceToSearchFor>();
InterfaceToSearchFor instanceOfInterface = loader.CreatePlugin(AppDomain.CurrentDomain.BaseDirectory);
如果这个答案或任何其他答案帮助你解决你的问题,请通过点击勾选标记作为答案。如果你觉得这是一个很好的解决方案,请投票来表达你的感激之情。我只是觉得我应该提一下,因为看起来你对其他问题都不接受答案。
看一下MEF。它应该提供你正在寻找的东西。
使用反射也是一种选择,但如果你问我的话,MEF将是更好的选择。
我觉得你可以这样开始
Assembly assembly = Assembly.LoadFrom("Something.dll");
Type type = assembly.GetType("SomeType");
object instanceOfSomeType = Activator.CreateInstance(type);
那么你可以使用
我正在处理类似的事情,其中客户可能安装了不同版本的第三方DLL,尽管名称和位置是相同的。如果我们没有引用正确的版本,我们就会失败。我正在使用反射来识别版本,但是我需要修改设置以根据版本使用不同的DAL类,或者通过接口使DAL版本独立。
我倾向于后者。如果你让一个"假DLL在代码中实现一个接口,您想调用的所有方法从目标组件,并通过在实际的类型作为参数,但接口,那么你应该能够使用所有的方法在设计时根据您的模型代码和编译实现,甚至你的测试,但是当你在运行时加载实际装配的结果真正的组装。让我知道这是否适合你,我也会让你知道的。
乔伊摩根
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;
}
上面的答案基本上是你所需要的。你可以尝试在程序启动时加载要插入到应用程序中的所有dll:
// 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
}
如何引用dll及其类型:
// 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" });
你可能需要告诉你的应用配置探测你的插件目录。我假设一个插件的子目录,你可以探测一个子目录路径列表。
...
<runtime>
<assemblyBinding ...
<probing privatePath="plugins" />
...
您将需要一些东西来告诉您要实现哪种类型(可能是配置映射)。这个接口,据我所知,将只是提供一个合约,所有的插件实现提供一个预期的方法,通过反射调用。