Assembly.Load("程序集名");Assembly.LoadFrom("程序集实际路径");

反射Assembly.Load("程序集").CreateInstance("命名空间.类")

在编程中,使用反射(IoC)是一个很好的架构。在.Net中,System.Reflection命名空间提供了对反射的支持。然而,很多朋友在使用Assembly.Load()方法时, 却不能正确装载程序集。比如,很多朋友在模仿PetShop的框架时,使用这样的调用方式:

string assemblyName = ConfigurationManager.AppSettings["webDAL"];
string constructor = ConfigurationManager.AppSettings["constructorClass"];
 return (IExample)Assembly.Load(assemblyName).CreateInstance(constructor, false);

然而,在Assembly.Load()方法处,经常出现未能加载程序集的错误:

未能加载文件或程序集“webDAL”或它的某一个依赖项。系统找不到指定的文件

Assembly.Load(assemblyName)实际上是在assemblyName.dll文件中查找类custructor的定义。例如,Assembly.Load("PetShop.SQLServerDAL").CreateInstance("PetShop.SQLServerDAL.Cateogry"),就是在PetShop.SQLServerDAL.dll程序集中查找PetShop.SQLServerDAL.Category类。而在自己定义类库时,往往忽视了生成的程序集的名称。

在类库项目上点击右键->属性,可以设定生成的程序集的文件名。只有正确设置了,才能在Assembly.Load(assemblyName)方法中避免找不到程序集的错误。

一.Load方法
1.Load(AssemblyName) 在给定程序集的 AssemblyName 的情况下,加载程序集。
例1: TestLib.LzdTest lzdTeset = (TestLib.LzdTest)Assembly.Load("TestLib").CreateInstance("TestLib.LzdTest");

用Reflector查看源码如下:
public static Assembly Load(AssemblyName assemblyRef)
{
    StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
    return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, ref lookForMyCaller, false, false);
}

2.Load(AssemblyString) 通过给定程序集的长格式名称加载程序集。
例2: TestLib.LzdTest lzdTeset = (TestLib.LzdTest)Assembly.Load("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").CreateInstance("TestLib.LzdTest");

用Reflector查看源码如下:
public static Assembly Load(string assemblyString)
{
    StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
    return RuntimeAssembly.InternalLoad(assemblyString, null, ref lookForMyCaller, false);
}

[MethodImpl(MethodImplOptions.NoInlining), SecurityCritical]
internal static RuntimeAssembly InternalLoad(string assemblyString, Evidence assemblySecurity, ref StackCrawlMark stackMark, bool forIntrospection)
{
    if (assemblyString == null)
    {
        throw new ArgumentNullException("assemblyString");
    }
    if ((assemblyString.Length == 0) || (assemblyString[0] == '\0'))
    {
        throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
    }
    AssemblyName assemblyRef = new AssemblyName();
    RuntimeAssembly assembly = null;
    assemblyRef.Name = assemblyString;
    if (assemblyRef.nInit(out assembly, forIntrospection, true) == -2146234297)
    {
        return assembly;
    }
    return InternalLoadAssemblyName(assemblyRef, assemblySecurity, ref stackMark, forIntrospection, false);
}

总结: 使用Load方法加载程序集,特别是强命名程序集,能在程序集上应用安全和部署策略,一般情况下都应该优先使用这个方法。

二.LoadFrom (已知程序集的文件名或路径,加载程序集。)
例3: TestLib.LzdTest lzdTeset = (TestLib.LzdTest)Assembly.LoadFrom("D:\\workspace\\LatestWebTestSite\\TestLib.dll").CreateInstance("TestLib.LzdTest");

用Reflector查看源码如下:
public static Assembly LoadFrom(string assemblyFile)
{
    StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
    return RuntimeAssembly.InternalLoadFrom(assemblyFile, null, null, AssemblyHashAlgorithm.None, false, false, ref lookForMyCaller);
}

[MethodImpl(MethodImplOptions.NoInlining), SecurityCritical]
internal static RuntimeAssembly InternalLoadFrom(string assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, bool forIntrospection, bool suppressSecurityChecks, ref StackCrawlMark stackMark)
{
    if (assemblyFile == null)
    {
        throw new ArgumentNullException("assemblyFile");
    }
    if ((securityEvidence != null) && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
    {
        throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
    }
    AssemblyName assemblyRef = new AssemblyName();
    assemblyRef.CodeBase = assemblyFile;
    assemblyRef.SetHashControl(hashValue, hashAlgorithm);
    return InternalLoadAssemblyName(assemblyRef, securityEvidence, ref stackMark, forIntrospection, suppressSecurityChecks);
}

MSDN: LoadFrom 方法具有以下缺点。请考虑改用 Load。
1.如果已加载一个具有相同标识的程序集,则即使指定了不同的路径,LoadFrom 仍返回已加载的程序集。
2.如果用 LoadFrom 加载一个程序集,随后加载上下文中的一个程序集尝试加载具有相同显示名称的程序集,则加载尝试将失败。对程序集进行反序列化时,可能发生这种情况。

总结: LoadFrom只能用于加载不同标识的程序集, 也就是唯一的程序集, 不能用于加载标识相同但路径不同的程序集。

从例子1,2,3的源代码中可以看出来, 三者归根结都是调用RuntimeAssembly.InternalLoadAssemblyName()方法的.

三.LoadFile (加载指定路径上的程序集文件的内容。)
例4: TestLib.LzdTest lzdTeset = (TestLib.LzdTest)Assembly.LoadFrom("D:\\workspace\\LatestWebTestSite\\TestLib.dll").CreateInstance("TestLib.LzdTest");

用Reflector查看源码如下:
public static Assembly LoadFile(string path)
{
    new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand();
    return RuntimeAssembly.nLoadFile(path, null);
}

[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
internal static extern RuntimeAssembly nLoadFile(string path, Evidence evidence);
 
extern 修饰符用于声明 由程序集外部实现的成员函数经常用于系统API函数的调用(通过 DllImport )。
注意,和DllImport一 起使用时要加上 static 修饰符也可以用于对于同一程序集不同版本组件的调用(用 extern 声明别名) 不能与 abstract 修饰符同时使用 。

这个方法也不能加载同标识不同路径的程序集,否则也提示错误:

[A]TestLib.LzdTest cannot be cast to [B]TestLib.LzdTest. Type A originates from 'TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither' at location 'D:\workspace\LatestWebTestSite\LatestWebTestSite\bin\TestLib.dll'. Type B originates from 'TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\25a52d02\3d6c3f29\assembly\dl3\c37d3dd1\72d288f9_135bcc01\TestLib.DLL'.

总结: 这个方法是从指定的文件来加载程序集,它是调用外部的API实现的加载方式,和上面Load,LoadFrom方法的不同之处是这个方法不会加载此程序集引用的其他程序集,也就是不会加载程序的依赖项。

1、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("a.dll"),则载入a.dll,假如a.dll中引用了b.dll的话,b.dll并不会被载入。
Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,b.dll也会被载入。
2、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如a.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("2\\a.dll")载入版本2时,不能载入,而是返回版本1。
Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。

Assembly.Load相关推荐

  1. Assembly.Load()不能加载程序集的问题

    会出现"未能加载文件或程序集"Com.SQLServerDAL"或它的某一个依赖项.系统找不到指定的文件"的情况.就是无法找到该程序集,主要是没理解它运行的机制 ...

  2. 你了解 Assembly.Load 吗?

    我们在使用C# 语言的Assembly.Load 来加载托管程序集并使用反射功能时,一般需要先通过Assembly.Load(), Assembly.LoadFrom() 等方法将目标托管程序集加载到 ...

  3. C#反射之Assembly.Load,Assembly.LoadFile 与 Assembly.LoadFrom方法介绍

    一些关于C#反射的知识,估计也就最多达到使用API的程度,至于要深入了解,以现在的水平估计很难做到,所以下面此篇文章,以作为一个阶段的总结. 对于反射的总结,我想从以下几个方面展开,首先是反射程序集, ...

  4. 关于反射Assembly.Load(程序集).CreateInstance(命名空间.类)

    关于反射Assembly.Load("程序集").CreateInstance("命名空间.类") 而不管在哪一层写这段代码其中的("程序集" ...

  5. Assembly.Load,LoadFile,LoadFrom

    在加载Assembly的时候有三种Load Context可以选择: Load Context 通常来说,当通过探测 GAC,host assembly store (if hosted), 或者 t ...

  6. Assembly.Load动态加载程序集而不占用文件

    方式一:占用文件的加载 Assembly assembly = Assembly.Load(path); 用上面的方法可以动态的加载到dll,但是用这种方法加载到的dll一直到程序运行结束都是占用的d ...

  7. Assembly.Load,Assembly.LoadFile 与 Assembly.LoadFrom

    Load为最佳方案,用完全限定名进行加载程序集.完全限定名为:程序集名称,version, Culture, PublicKeyToken LoadFile 方法用来来加载和检查具有相同标识但位于不同 ...

  8. Assembly中Load, LoadFrom, LoadFile以及AppDomain, Activator类中相应函数的区别

    Assembly和AppDomain的一些关于动态加载程序集的函数有些令人头疼,但细细研究后还是可以将他们区分的. 这些函数大致可以分为四类: 第一类:加载到Load Context内 Load Co ...

  9. Could not load file or assembly 'xxx' or one of its dependencies.

    Could not load file or assembly 'xxx' or one of its dependencies. The system cannot find the file sp ...

最新文章

  1. 长知识啦!字符也可以作为下标!_只愿与一人十指紧扣_新浪博客
  2. CentOS7 配置ISCSI targetcli 共享存储
  3. pycharm最左侧Tool Buttons显示不全的问题解决
  4. 动态创建 @ViewChild 导致运行时错误的原因分析
  5. 【三维深度学习】基于片元的渐进式三维点云上采样模型
  6. java 注册监听_java注册监听模型
  7. linux下mysql的用户名,linux下设置mysql用户名及密码
  8. [HTML5实现人工智能]小游戏《井字棋》发布,据说IQ上200才能赢
  9. SCVMM 2012 R2运维管理十一之:添加Hyper-v群集
  10. KM算法--带权二分匹配
  11. cgo的效率 golang_golang rsa 和 cgo (openssl) 性能对比
  12. 移动MM收费:钱不是问题
  13. elasticsearch安装教程
  14. 微星主板 B450 迫击炮 无线网卡 无法上网解决办法
  15. SCI论文重复率与降重
  16. HTML实现舔狗日记
  17. Python+ASAquick+PSIPred蛋白质序列特征计算,ASAquick安装调用(Linux)
  18. 随笔小记-12.31
  19. 异步三部曲之promise
  20. 【量化】实战获取Fama-French三因子模型的数据源

热门文章

  1. Crackme006 - 全新160个CrackMe深度解析系列(图文+视频+注册机源码)
  2. 关于辛普森积分法的研究
  3. centos安装和配置masakari(stein版本)
  4. 3D空间中射线与轴向包围盒AABB的交叉检测算法
  5. 2020材料员-通用基础(材料员)考试及材料员-通用基础(材料员)实操考试视频
  6. idea如何自制插件_Minecraft插件开发教程-开发环境配置 [原创]
  7. 用Python分析幸福指数
  8. “木兰”套壳Python引热议,该对浮夸式造假说“不”
  9. Linux网络 DHCP
  10. python设置背景图片