在运行时加载.Net引用

4
我有以下需求:
  • 我有一个C#/.Net控制台应用程序,它引用了'System.Data.Sqlite.dll'
  • 'System.Data.Sqlite.dll'没有在GAC中注册(我不想要)
  • 我不想将其保存在可执行文件(.exe)所在的目录中。

  • 如何将'System.Data.Sqlite.dll'文件安全地保存在其他目录中,并在运行时加载,以便在应用程序代码中引用之前?


3
把dll文件放在与.exe文件相同的位置有什么问题? - thmsn
4
为什么不能将DLL文件放在EXE目录中?这是依赖DLL的标准位置,.Net会自动查找,无需您额外努力。 - MusiGenesis
这是一个Windows客户端(Win Forms)应用程序还是Web应用程序? - Kane
1
我想做的事情类似于插件加载。插件dll文件保存在与.exe文件不同的目录中,我希望在应用程序启动时加载它。 - Palani
8个回答

10

您可以使用手动程序集解析来实现此操作。

您需要在当前AppDomain中提供一个委托给AssemblyResolve事件。

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += assemblyResolver.ResolveEventHandler;

当应用程序有任何无法解析的程序集引用时,它将调用此委托以获取已解决的程序集。 然后,您只需从委托返回所请求的程序集即可:

Assembly assembly = Assembly.LoadFrom (assemblyPath);
return assembly;
希望这可以帮助到你。

4
我不确定为什么你想再做一遍,这是违反最佳实践的行为。但是回答你的问题: 你可以使用


Assembly.LoadFrom Method (String path)

来自 System.Reflection 命名空间

并在 app.config 文件中设置路径

在 MSDN 上的 Assembly.LoadFrom


我无法将路径添加到app.config文件中,DLL目录可能在运行时更改。有什么解决方法吗? - Palani
动态链接库目录为什么会在运行时改变? - Martin Harris
@Palani - 你能简要解释一下你的使用情况吗? - abhilash

4
你可以在应用程序的配置文件中添加一个探测元素。这样可以检查除默认文件夹外的其他文件夹是否存在所需的库。请参见此处
出于安全原因,它仍必须位于exe文件夹下方。

1

您需要使用反射(使用 System.Reflection 命名空间)结合 Assembly.LoadFromType.GetTypeType.GetMethod 来加载您的 dll 和方法。

以下是一个示例,演示如何使用反射从在运行时加载的 dll 中动态调用方法。

static string DynamicMethodCall(string dllPath, string someClass, string someMethodName, object[] parameters)
        {
            Assembly dll = Assembly.LoadFile(dllPath);

            Type type = dll.GetType(someClass);

            if (type == null)
            {
                Exception ex = new Exception("class not found");
                throw ex;
            }

            MethodInfo method = type.GetMethod(someMethodName);

            if (method == null)
            {
                Exception ex = new Exception("method not found");
                throw ex;
            }

            if (parameters.Length >= 1)
            {
                object[] myparam = new object[1];
                myparam[0] = parameters;
                return (string)method.Invoke(null, myparam);
            }
            else
            {
                return (string)method.Invoke(null, null);
            }
        }

1
你可以使用 Assembly.LoadFrom(filename)
但正如评论者所指出的,我不明白为什么你要这样做?

0
您可以将DLL作为嵌入式资源包含在EXE项目中,当应用程序启动时,您可以将DLL保存到EXE文件目录中(并在应用程序结束时删除它,尽管我不知道将DLL放在EXE目录中有什么问题)。只要在加载任何引用SqlLite的内容之前执行提取操作,这将起作用。
更新:由于您想要进行插件式DLL,因此您可以将DLL保留在单独的目录中,并在应用程序启动时将其复制到EXE文件夹中。

0
我看不出来为什么需要将程序集与 exe 文件分开,但其中一种方法是将它们放在 exe 文件所处的目录下的一个单独目录中,并在 app.config 文件中包含一个探查元素。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接