C#反射的实现
一,什么是反射?
1,System.Reflection 命名空间中的类与 System.Type 使你能够获取有关加载的程序集和其中定义的类型的信息,如类、接口和值类型。 可以使用反射在运行时创建、调用和访问类型实例。
2,System.Type 类对于反射起着核心的作用。 当反射请求加载的类型时,公共语言运行时将为它创建一个 Type。 您可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。
3,动态的创建类型的实例,将类型邦定到现有对象,或从现有对象中获取类型 (动态获取程序集)
4,应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射
二,简单工厂的设计
项目各层之间的引用情况:
FanSheLK引用IFanSheLK
DataBLL引用IFanSheLK和DataDemo
DataDemo引用IFanSheLK
MvcTest引用DataBLL,FanSheLK
三,代码如下
FanSheLK代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IFanSheLK; namespace FanSheLK
{
public class Class1 : IClass1
{
public void aa()
{
Console.WriteLine("aa");
}
}
}
IFanSheLK的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace IFanSheLK
{
public interface IClass1
{
void aa();
}
}
DataDemo代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IFanSheLK;
using System.Reflection; namespace DataDemo
{
public sealed class DataAccess
{
private static readonly string AssemblyPath = "FanSheLK";
public DataAccess()
{ } #region CreateObject //不使用缓存
private static object CreateObjectNoCache(string AssemblyPath, string classNamespace)
{
try
{
//使用 Assembly 来定义和加载程序集,加载程序集清单中列出的模块,以及在此程序集中定位一个类型并创建一个它的实例。
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch(Exception e)
{
return e.Message;
} }
#endregion /// <summary>
/// 创建数据层接口。
/// </summary>
public static IClass1 CreateUser()
{
string ClassNamespace = "FanSheLK.Class1";
object objType = CreateObjectNoCache(AssemblyPath, ClassNamespace);
return (IClass1)objType;
} }
}
DataBLL的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataDemo;
using IFanSheLK; namespace DataBLL
{
public class Class1
{
public readonly IClass1 a = DataAccess.CreateUser();
public Class1() { }
public string Test() {
return "成功";
}
}
}
MVC的HomeController.cs的调用实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DataBLL; namespace MvcTest.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/ public ActionResult Index()
{
Class1 a = new Class1();
a.Test();
return View();
} }
}
三,然而在实现反射的过程中最容易出现的问题就是:未能加载文件或程序集“xxx(FanSheLK)”或它的某一个依赖项。系统找不到指定的文件。
这是由于反射中的这个造成的Assembly.Load(AssemblyPath).CreateInstance(classNamespace);,切确来说是Assembly.Load(AssemblyPath)这找不到要反射的类库
PS: 到这个时候就要检查下你加载DLL路径是否错误,即DLL文件存在,但加载路径不正确
但是在此之前你要明白:Assembly.Load()要加载的DLL路径究竟是哪里!!!!!!!!!!
根据问题,有以下猜测:
1》在反射方法类库的\bin\Debug下?(即我项目的DataDemo\bin\Debug)
2》在MVC站点的\bin\Debug下?(即我项目的MvcTest\bin\Debug)
3》在反射实现类库的\bin\Debug下?(即我项目的DataBLL\bin\Debug)
解决如下:
1》在反射方法类库(DataDemo),添加要反射类库(FanSheLK)的引用,将生成的FanSheLK.dll到项目的DataDemo\bin\Debug下,但是经过实验证明,这是错误的,一样提示:未能加载文件或程序集“xxx(FanSheLK)”或它的某一个依赖项。系统找不到指定的文件
2》在MVC站点添加引用,添加要反射类库(FanSheLK)的引用,将生成的FanSheLK.dll到项目的\bin\Debug下,神奇的结果出现了,方法Assembly.Load成功加载了,但是还需要继续实验下去。。。。
3》在反射实现类库(DataBLL),添加引用,添加要反射类库(FanSheLK)的引用,将生成的FanSheLK.dll到项目的\bin\Debug下,神奇的结果又出现了,方法Assembly.Load成功加载了
这样又出现新的问题:为什么会有两种假设成功?根据以上两种情况分别引用,我们查看他们的相同的地方和不相同的地方
1》先将反射实现类库(DataBLL)和在MVC站点的项目的\bin\Debug下DLL都删掉
2》在MVC站点添加引用,添加要反射类库(FanSheLK)的引用,项目重新生成,我们会发现FanSheLK.dll会在MVC站点的\bin\Debug下生成,而反射实现类库(DataBLL)并没有
3》在反射实现类库(DataBLL),添加引用,添加要反射类库(FanSheLK)的引用,项目重新生成,在这一次,我们会发现FanSheLK.dll会在MVC站点的\bin\Debug下和反射实现类库(DataBLL)下生成
4》经过以上对比我们发现共同点:FanSheLK.dll会在MVC站点的\bin\Debug下生成,那我们把他删掉,测试
5》得出结论:Assembly.Load()寻找的地址是在MVC站点的\bin\Debug下,则如果反射出现:未能加载文件或程序集“xxx(FanSheLK)”或它的某一个依赖项。系统找不到指定的文件。错误时:我们应该查看该目录下是否存在反射类库的DLL
PS:为什么在反射实现类库(DataBLL),添加引用,添加要反射类库(FanSheLK)的引用,项目重新生成,FanSheLK.dll会在MVC站点的\bin\Debug下和反射实现类库(DataBLL)下同时生成?
原因是我的DataBLL被MVC站点引用,所以会生成DataBLL的引用的DLL,然而这样的引用在VS中执行没问题,然而如果使用IIS发布出去就会出现反射失败,这又是为什么呢???
原因:也是查找不到路径,如果需要执行成功,我们就要在MVC站点下添加反射库(FanSheLK)的引用,而不是在反射实现库(DataBLL)中添加(FanSheLK)的引用
四,命名空间或者路径,经过排查发现都正确,但是还是报这个错误:调用的目标发生了异常。这时候问题可能就是在调用的类,就是项目的反射类库(FanSheLK)
1》有可能该类库中的反射类定义的属性出现错误
2》有可能反射类库(FanSheLK)引用了其他类库,出现继承,然而反射却找不到反射类库(FanSheLK)引用类库的路径
五,如果类库存在实体模型 会出现错误:指定的命名连接在配置中找不到、非计划用于 EntityClient 提供程序或者无效。
1》原因:因为实体模型的构造函数方法失败
/// <summary>
/// 请使用应用程序配置文件的“JXCEntities”部分中的连接字符串初始化新 JXCEntities 对象。
/// </summary>
public JXCEntities() : base("name=JXCEntities", "JXCEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
解决方法:将实体模型的连接写在站点(MVC的Web.config)的配置文件下,则读取配置文件成功
<connectionStrings>
<add name="JXCEntities" connectionString="metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=XXX;user id=XX;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
五,反射构造带参的例子
1》传递变量
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection; namespace FanShe3
{
class Test
{
public Test(string Say)
{
Console.WriteLine(Say);
}
}
class Program
{
static void Main(string[] args)
{
Test t;
string Say = "哈哈!!创建成功";
//开始创建反射,这个是获取当前程序集的意思,如果需要反射类库可以使用Assembly.Load的方法
Assembly asm = Assembly.GetExecutingAssembly();
//需要注意的地方是,如果反射的构造函数带参只是一个,这里创建的也必须是一个参数的Object数组,而且顺序也必须和构造函数一样
object[] Obj = new object[];
Obj[] = Say;
t = (Test)asm.CreateInstance("FanShe3.Test", true, BindingFlags.Default, null, Obj, null, null); Console.ReadKey();
}
}
}
2》传递对象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection; namespace FanShe4
{
class Test
{
public Test(Test2 t2)
{
t2.Say();
}
} public class Test2
{
public void Say()
{
Console.WriteLine("哈哈!!创建成功");
}
} class Program
{
static void Main(string[] args)
{
Test t;
Test2 t2 = new Test2();
//开始创建反射,这个是获取当前程序集的意思,如果需要反射类库可以使用Assembly.Load的方法
Assembly asm = Assembly.GetExecutingAssembly();
//需要注意的地方是,如果反射的构造函数带参只是一个,这里创建的也必须是一个参数的Object数组,而且顺序也必须和构造函数一样
object[] Obj = new object[];
Obj[] = t2;
t = (Test)asm.CreateInstance("FanShe4.Test", true, BindingFlags.Default, null, Obj, null, null); Console.ReadKey();
}
} }
综上,如果出现错误:有路径问题,传参数的数量不对等
C#反射的实现的更多相关文章
- 隐私泄露杀手锏 —— Flash 权限反射
[简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...
- Java学习之反射机制及应用场景
前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...
- 关于 CSS 反射倒影的研究思考
原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 运用Mono.Cecil 反射读取.NET程序集元数据
CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...
- .NET面试题系列[6] - 反射
反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- C++的性能C#的产能?! - .Net Native 系列五:.Net Native与反射
此系列系小九的学堂原创翻译,翻译自微软官方开发向导,一共分为六个主题.本文是第五个主题:.Net Native与反射. 向导文链接:<C++的性能C#的产能?! - .Net Native 系列 ...
- [源码]Literacy 快速反射读写对象属性,字段
Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...
- SI与EMI(一) - 反射是怎样影响EMI
Mark为期两天的EMC培训中大概分成四个时间差不多的部分,简单来说分别是SI.PI.回流.屏蔽.而在信号完整性的书籍中,也会把信号完整性分为:1.信号自身传输的问题(反射,损耗):2.信号与信号之间 ...
随机推荐
- 使用transporter同步MongoDB数据到es
由于logstash不支持MongoDB自定义主键导入es,所以使用transporter导入数据. 版本:es5.x,transporter0.25, es6以上不允许一个索引下面多个type,tr ...
- 北京太速科技有限公司 layout 事业部
涵盖领域设计能力 ·通信板卡:PCI/PCIE/CPCI/VPX/光通信/无线通信/射频雷达/显卡 1.最小线宽:2MIL·主板服务器:电脑主板/交换机/服 ...
- 【LeetCode】字符串 string(共112题)
[3]Longest Substring Without Repeating Characters (2019年1月22日,复习) [5]Longest Palindromic Substring ( ...
- Vue----v-if 条件渲染
先看一个使用vue v-if的小例子 <div id="example"> <p>小明和小李和小新,小月正在捉迷藏此时</p> <p> ...
- java 方法返回多个值
package java03; /* * 一个方法可以有0,1或者多个参数,但是返回值只能有0或者1个返回值,不能有多个返回值 * 但是如果希望有多个返回值,应该怎么办? * 答:使用数组作为返回值类 ...
- vue内置组件——transition简单原理图文详解
基本概念 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如 Animate.css 在过渡 ...
- Spring---Spring Aware
1.概述 1.1.Spring中的 所有Bean 对Spring容器的存在 是没有意识的(即你可以将容器换成别的容器,这样使用容器与Bean之间的耦合度很低): 但在实际项目中,不可避免的要用到 ...
- python3-Django初始化项目详细
0.背景 近期在学习django,在初始化项目的时候遇到了一丢坑,记录一下. 1.安装django 下载安装包解压出来后,python3 setup.py install 即可 2.创建项目 djan ...
- win 10配置安装iis
站长喜欢本地配置iss调试网站后发布到网上,但是前提是系统得配置好iis.随着Win10的出现,越来越多的人装上了Win10, 但是小编最近发现很多旧版本windows系统用户在升级到windows ...
- web uploader 上传大文件总结
这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...