Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 加载重命名的程序集并创建实例_C#_Sqlite_Reflection_.net Assembly_Invoke - Fatal编程技术网

C# 加载重命名的程序集并创建实例

C# 加载重命名的程序集并创建实例,c#,sqlite,reflection,.net-assembly,invoke,C#,Sqlite,Reflection,.net Assembly,Invoke,我正在开发使用mixmode System.Data.SQLite.dll的软件。我需要在一个文件夹中交付其中4个(针对.net 2.0和4.0的x86和x64)。这就是为什么我把它改名为 System.Data.SQLite.x64.dll 基于平台,我将加载其中一个,并使用反射创建SQLiteConnection var assembly = Assembly.LoadFile(@"d:\sqlite-netFx20-binary-bundle-x64-2005-1.0.92.0\Syste

我正在开发使用mixmode System.Data.SQLite.dll的软件。我需要在一个文件夹中交付其中4个(针对.net 2.0和4.0的x86和x64)。这就是为什么我把它改名为

System.Data.SQLite.x64.dll

基于平台,我将加载其中一个,并使用反射创建
SQLiteConnection

var assembly = Assembly.LoadFile(@"d:\sqlite-netFx20-binary-bundle-x64-2005-1.0.92.0\System.Data.SQLite.x64.dll");
Type t = assembly.GetExportedTypes()[8];
object sqliteCon = Activator.CreateInstance(t, @"Data Source=d:\nwind.db;Version=3;");
最后一行抛出一个异常

类型的未处理异常 mscorlib.dll中出现“System.Reflection.TargetInvocationException”

无法加载DLL“System.Data.SQLite.DLL”:指定的模块 找不到。(来自HRESULT的异常:0x8007007E)

我没有在项目中引用SQLite.dll。 如果dll有它的原始名称,我运行这段代码没有问题

程序集
对象上调用CreateInstance并从类型中获取构造函数并调用它会引发相同的异常:

//ConstructorInfo ctor = t.GetConstructor(new[] { typeof(string) });
//object instance = ctor.Invoke(@"Data Source=d:\nwind.db;Version=3;");

//object ass = assembly.CreateInstance("System.Data.SQLite.SQLiteConnection", false, BindingFlags.CreateInstance, null, new object[] { @"Data Source=d:\nwind.db;Version=3;" }, null, null);
问题:为什么会发生这种情况,我如何解决


谢谢。

出现此问题是因为您已重命名.DLL。除非您想更改mete数据中的某些变量,否则必须以某种方式重命名库

我以前遇到过这个问题,这是我使用的解决方案:

        string tempFile = string.Format("{0}\\{1}", System.IO.Path.GetTempPath(), "System.Data.SQLite.dll");
        System.IO.File.WriteAllBytes(tempFile, System.IO.File.ReadAllBytes(@"C:\System.Data.SQLite_x64.dll"));
        var assembly = Assembly.LoadFile(tempFile);
        Type t = assembly.GetExportedTypes()[8];
        object sqliteCon = Activator.CreateInstance(t, @"Data Source=d:\nwind.db;Version=3;");  
它会将文件的副本创建到您计算机上的临时目录中,并将其重命名回原始名称

在关闭应用程序时,不要忘记删除文件

--编辑:

我上面使用的方法并不适合您的项目,因为您只需确定一次所需的库。因此,我会在程序第一次加载时重命名正确的库,这样您就不必在用户每次启动程序时创建临时文件:

        string myPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
        string originalName = "System.Data.SQLite.dll";

        // If we haven't already renamed the right library
        if (!System.IO.File.Exists(string.Format("{0}\\{1}", myPath, originalName)))
        {
            foreach (var file in System.IO.Directory.GetFiles(myPath))
            {
                string fileName = System.IO.Path.GetFileName(file);
                if (fileName.StartsWith("System.Data.SQLite."))
                {
                    // !! Do your platform checks here !!
                    // ..

                    // Copy the file with its original name
                    System.IO.File.Move(file, file.Replace(fileName, "System.Data.SQLite.dll"));
                    // Delete old file (not necessary)
                    System.IO.File.Delete(file);
                }
            }
        }

        var assembly = Assembly.LoadFile(string.Format("{0}\\{1}", myPath, originalName));

您看到这种行为的原因是,您可能正在编译dll后更改其文件名。DLL的原始文件名属性存储在DLL编译过程中的元数据中。这就是为什么重命名DLL并不是一个好主意,而是使用新名称重新编译它们


为所有用例重新编译DLL 4次,问题就会消失。

IMHO创建一个安装程序,为系统提供合适的DLL,而不是将4个DLL全部发送并重命名,这会更简单。@DStanley不在我的情况下,因为我的软件是软件开发人员的类库,所以我必须提供所有DLL+1 I喜欢你的编辑,但我忘了提到,我的软件是一个面向开发人员的类库。开发人员可能会在其项目中引用其中一个DLL,该项目也使用我的库,因此文件重命名不是我最喜欢的解决方案。谢谢。我理解,在你的情况下,你不会同意文件重命名。您可以在程序集中循环其引用的库,并检查其中一个引用是否是您的库,如果不是,您可以始终将自己的库放在磁盘上(或者,如果已经存在,请重命名它)。我刚刚尝试过这样做,但仍然得到相同的异常。现在我真的不知道为什么。如果你有空余时间,可以试试吗。我只留下了SQLite.Interop.2013、SQLite.Interop.Static.2013、System.Data.SQLite.2013和System.Data.SQLite.Module.2013。我在SQLite.Interop.Static.2013中修改了目标名称,现在dll有了新名称。Thanks@VladL真奇怪。因为任何地方都不应该提及旧名称。除非有一个DLL本身。不幸的是,我现在无法做到这一点。但我建议您使用Fuslogvw.exe转储Fusion活动(dll解析)。它将帮助您查看哪个模块正在尝试加载该DLL,以及在何处查找该DLL。