zoukankan      html  css  js  c++  java
  • C#反射中Assembly.Load及Assembly.Load.CreateInstance

    错误信息:

     

    “/Web”应用程序中的服务器错误。

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

    说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

    异常详细信息: System.IO.FileNotFoundException: 未能加载文件或程序集“PetShop.SQLServerDAL”或它的某一个依赖项。系统找不到指定的文件。

    源错误:

    行 21:             //string className = path + ".Category";
    行 22:             //return (PetShop.IDAL.ICategory)Assembly.Load(path).CreateInstance(className);
    行 23:             return (PetShop.IDAL.ICategory)Assembly.Load("PetShop.SQLServerDAL").CreateInstance("PetShop.SQLServerDAL.Category");
    行 24:         }
    行 25: 

    源文件: J:\MyPetShop\Task042\PetShop\DALFactory\DataAccess.cs    行: 23

    错误原因:Web层bin文件夹下的文件名是"SQLServerDAL",不是"PetShop.SQLServerDAL"

    参考资料:

    C#反射中Assembly.Load及Assembly.Load.CreateInstance

    在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系: 
    System.Reflection命名空间
    (1)  AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器
    (2)  Assembly:程序集类
    (3)  Module:模块类
    (4)  Type:使用反射得到类型信息的最核心的类
    他们之间是一种从属关系,也就是说,一个AppDomain可以包含N个Assembly,一个Assembly可以包含N个Module,而一个Module可以包含N个Type. AppDomain这个类我们等下再来讲解。我们先关注Assembly个类,在程序中,如果我们要动态加载一个程序集怎么办呢?有几种方式可以使用,分别是Load,LoadFrom和LoadWithPartialName三个Assembly的静态方法.
      先来讲解Assembly.Load方法,该方法会有多个重载版本,其中一个就是提供程序集的详细信息,即程序集的标识,包括程序集的名称,版本,区域信息,公有密钥标记,全部都是以一个字符串的形式提供,例如:"MyAssembly,Version=1.0.0.0,culture=zh-CN,PublicKeyToken=47887f89771bc57f”.
       那么,使用Assembly.Load加载程序集的顺序是怎样的呢?首先它会去全局程序集缓存查找,然后到应用程序的根目录查找,最后会到应用程序的私有路径查找。
       当然,如果你使用的是弱命名程序集,也即只给出程序集的名称,那么这个时候,CLR将不会在程序集上应用任何安全或者部署策略,而且Load也不会到全局缓存程序集中查找程序集。
    Assembly.Load("")的使用说明如下;  
      并不是命名空间。常用的是程序集名称,也就是dll的名称  
        重载列表    
      名称说明 
      Assembly.Load(AssemblyName)在给定程序集的AssemblyName的情况下,加载程序集。 
      由.NETCompactFramework支持。
      Assembly.Load(Byte[])加载带有基于通用对象文件格式(COFF)的图像的程序集,该图像包含已发出的程序集。将该程序集加载到调用方的域。 
      Assembly.Load(String)通过给定程序集的长格式名称加载程序集。 
    由.NETCompactFramework支持。
    Assembly.Load(AssemblyName,Evidence)在给定程序集的AssemblyName的情况下,加载程序集。使用提供的证据将该程序集加载到调用方的域中。
    Assembly.Load (Byte[],Byte[])加载带有基于通用对象文件格式(COFF)的图像的程序集,该图像包含已发出的程序集。
    Assembly.Load(String,Evidence)通过给定的程序集的显示名称来加载程序集,使用提供的证据将程序集加载到调用方的域中。
    Assembly.Load(Byte[],Byte[],Evidence)加载带有基于通用对象文件格式(COFF)的图像的程序集,该图像包含已发出的程序集。

    关于反射Assembly.Load("程序集").CreateInstance("命名空间.类")
    而不管在哪一层写这段代码其中的("程序集")读取的实际是web层bin文件夹下的dll,也就是说你反射的类的程序集dll在web层的bin下必须有
    注意CreateInstance()一定是命名空间.类名,否则创建的实例为空
    Assembly.Load("程序集名")
    Assembly.LoadFrom("程序集实际路径")

    什么是Assembly(程序集)?
    Assembly是一个包含来程序的名称,版本号,自我描述,文件关联关系和文件位置等信息的一个集合。在.net框架中通过Assembly类来支持,该类位于System.Reflection下,物理位置位于:mscorlib.dll。
    Assembly能干什么?
    我们可以通过Assembly的信息来获取程序的类,实例等编程需要用到的信息。
    一个简单的演示实例:
    1.建立一个Console工程名为:NamespaceRef
    2.写入如下代码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Reflection;
     5
     6 namespace NamespaceRef
     7 {
     8     class Program
     9     {
    10         static void Main(string[] args)
    11         {
    12             Country cy;
    13             String assemblyName = @"NamespaceRef";
    14             string strongClassName = @"NamespaceRef.China";
    15             // 注意:这里类名必须为强类名
    16             // assemblyName可以通过工程的AssemblyInfo.cs中找到
    17             cy = (Country)Assembly.Load(assemblyName).CreateInstance(strongClassName);
    18             Console.WriteLine(cy.name);
    19             Console.ReadKey();
    20         }
    21     }
    22
    23     class Country
    24     {
    25         public string name;
    26     }
    27
    28     class Chinese : Country
    29     {
    30         public Chinese()
    31         {
    32             name = "你好";
    33         }
    34     }
    35
    36     class America : Country
    37     {
    38         public America()
    39         {
    40             name = "Hello";
    41         }
    42     }
    43 }


    由于Assembly的存在给我们在实现设计模式上有了一个更好的选择。
    我们在开发的时候有时候会遇到这样的一个问题,根据对应的名称来创建指定的对象。如:给出chinese就要创建一个chinese对象,以前我们只能这样来写代码:

    1 if (strongClassName == "China")
    2     cy = new China();
    3 else if (strongClassName == "America")
    4     cy = new America();

    那么如果我们有很长的一系列对象要创建,这样的代码维护起来是很困难的,而且也不容易阅读。现在我们可以通过在外部文件定义类的程序集名称和类的强名称来获得这样一个实例,即易于理解,又增强了扩展性还不用修改代码。
    cy = (Country)Assembly.Load(assemblyName).CreateInstance(strongClassName);

     

     

     

     

    创建一个文件,在解决方案里有两部分:声明引用和代码实体.

     

    声明引用是:using System,表示引用了System名称空间下的所有成员,就是引用了所有system派生出来的类.

     

    还有一个叫做AssemblyInifo.cs的文件.

     

    Assembly是用于建立.net应用程序的一部分,他带有版本信息和自描述信息,并可以重复使用.

     

    一个简单的Assembly可以是单个可执行文件,包含发布和版本信息,但通常会包含多个可执行文件和资源文件.

     

    Assembly定义了安全,发布和类型解析,他是可以执行的最小单元,运行环境只能执行位于Assembly中的代码.

     

    Assembly对于公共语言运行环境(Common Language Runtime,CLR) 非常重要,因为CLR是用他来定位和安全的执行代码的.

     

    AssemblyTitle          标题

     

    AssemblyDescription 描述

     

    AssemblyConfiguration 配置

     

    AssemblyComany 公司

     

    AssemblyProduct 产品

     

    AssemblyCopyright 版权

     

    AssemblyTrademark 商标

     

    AssemblyCulture 区域

     

    Assembly Version 版本信息,包括四个段值:主版本号,副版本号,修订号,编译次数.

    本篇文章来源于:开发学院 http://edu.codepub.com   原文链接:http://edu.codepub.com/2010/0909/25797.php

  • 相关阅读:
    linux---shell数组
    linux---shell传递参数
    Windows mysql免安装版配置。(版本号-5.6.45);
    contos 6.9 和 centos7 配置docker?
    数据库表的演化过程
    docker简单介绍。
    Linux 配置 mycat 和 分库分表配置。
    Linux 配置mysql 免安装版。
    mycat 简单介绍
    kibana 对es的简单操作。
  • 原文地址:https://www.cnblogs.com/java20130723/p/3211685.html
Copyright © 2011-2022 走看看