我正在尝试动态加载deleteBuffer
。
已安装System.Data.SqlClient
Nuget,但在项目中没有对其的引用。
我不知道nuget目录的正确路径。
有没有办法动态地做到这一点?
这是我的代码
System.Data.SqlClient
这是我的运行方式
internal static Type GetFastType(this string typeName, string assembly)
{
if (string.IsNullOrEmpty(assembly))
throw new Exception("AssemblyName cannot be empty");
if (!assembly.ToLower().EndsWith(".dll"))
assembly += ".dll";
var key = typeName + assembly;
if (CachedStringTypes.ContainsKey(key))
return CachedStringTypes.Get(key);
// Assembly.LoadFrom(assembly) // throw exception as the dll is not found
if (!CachedAssembly.ContainsKey(assembly))
CachedAssembly.Add(assembly, Assembly.LoadFrom(assembly));
return CachedStringTypes.GetOrAdd(key, CachedAssembly.Get(assembly).GetType(typeName, true, true));
}
答案 0 :(得分:1)
阅读此MSDN文章:Best Practices for Assembly Loading
似乎您假设System.Data.SqlClient.SqlConnection
类始终存在于System.Data.SqlClient.dll
内部。
这是一个错误的假设:
mscorlib.dll
和System.Data.dll
) 。您的代码无法假定特定的类位于特定的程序集文件中-这打破了.NET通过类型转发的向后兼容性的概念。
在您的情况下,您的代码假定System.Data.SqlClient.SqlConnection
存在于名为System.Data.SqlClient
的程序集文件中。这种假设在许多情况下是错误的,但在某些情况下是正确的。
这是System.Data.SqlClient
NuGet软件包的顶级目录结构:
观察包中如何为每个受支持的目标提供子目录(在本例中为MonoAndroid10,MonoTouch10,net46,net451,net461,netcoreapp2.1,netstandard1.2等)。软件包为每个目标提供了不同的程序集:
在面向.NET Framework 4.5.1,.NET Framework 4.6或.NET Framework 4.6.1时,分别来自net451
,net46
和net461
目录的文件) 将会被使用。这些文件夹包含一个名为System.Data.SqlClient.dll
的文件,其中不包含任何类。这是因为,当您以.NET Framework 4.x为目标时,System.Data.SqlClient
内部的基类库已经提供了System.Data.dll
(命名空间)类型,因此不需要任何其他类型。 (因此,如果仅针对.NET Framework 4.x构建,则根本不需要System.Data.SqlClient
NuGet程序包。
如果不相信我,以下是使用.NET Reflector工具(该工具可让您查看内部文件并反编译.NET程序集)的程序集文件内部的屏幕截图:
当通过.NET Standard定位其他平台时(即默认情况下不包括System.Data.dll
,或者System.Data.dll
不包括SqlClient
时),NuGet软件包将请使用netstandard1.2
,netstandard1.3
,netstandard2.0
目录,其中确实包含一个System.Data.SqlClient.dll
,其中确实包含{{ 1}}命名空间以及您要使用的类型。这是该程序集的屏幕截图:
以及其他平台,例如System.Data.SqlClient
,MonoAndroid
,MonoTouch
,xamarinios
等也具有自己的特定版本的汇编文件(或文件!)。
但是,即使您知道您的程序将仅在单个特定平台上运行,该平台上特定的NuGet程序包包含一个包含特定类型的程序集DLL-由于类型转发,它仍然是“错误的”:https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime < / p>
尽管类型转发意味着大多数引用某些程序集中类型的程序将继续正常运行,但不适用于基于反射的程序集加载和类型加载,这正是您的代码所要做的。考虑这种情况:
xamarintvos
NuGet软件包的新版本,该软件包现在具有两个程序集:
System.Data.SqlClient
(与以前相同,只是删除了System.Data.SqlClient.dll
,但设置了引用SqlConnection
的{{1}}属性)。[TypeForwardedTo]
(System.Data.SqlClient.SqlConnection.dll
类现在位于此程序集中)。System.Data.SqlClient.SqlConnection.dll
而不是SqlConnection
并枚举这些类型。现在,假设您已准备好不考虑所有建议,并且仍然编写假定特定程序集中存在特定类型的程序,那么该过程很简单:
System.Data.SqlClient.dll
答案 1 :(得分:0)
对于任何可能遇到相同问题的人,我都找到了解决方法
这是您以正确的方式加载正确的类型的方法
var type = Type.GetType($"{typeName}, {assembly}");
eg.
var type =Type.GetType("System.Data.SqlClient.SqlConnection, System.Data.SqlClient");
这样,它应该动态加载dll。
答案 2 :(得分:-1)
我认为您必须提供指向LoadFrom(...)
的完整路径。您应该知道应用程序的探测路径,因此只需将该路径连接到程序集的名称即可。除非对应用程序域进行一些麻烦,否则我认为从不位于探测路径的路径中加载是不费吹灰之力的。