我正在开发使用mixmode System.Data.SQLite.dll的软件。我需要在一个文件夹中提供其中的4个(x86和x64用于.net 2.0和4.0)。这就是我将其重命名为
的原因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具有原始名称,我运行此代码没有问题。
在assembly
对象上调用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);
问题:为什么会发生这种情况?我该如何解决?
感谢。
答案 0 :(得分:2)
出现此问题是因为您已重命名.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));
答案 1 :(得分:1)
您看到此行为的原因是您可能在编译后更改了dll的文件名。 DLL的原始文件名属性沿其编译存储在dll的元数据中。这就是为什么重命名dll而不是使用新名称重新编译它们并不是一个好主意。
为您的所有用例重新编译DLL 4次,问题就会消失。