当前位置: 首页 > news >正文

.NET 反射的使用

1.根据类名获取类实例

string className = "Company.BigProgram.BLL.TestClass";
Type type = Type.GetType(className);
if (type != null)
{
    Object obj = Activator.CreateInstance(type);
    bool b = obj is TestClass;
}

className是包含命名空间的类名
在这里只是根据类名创建了一个实例,但是没有将其转换为相应的实体类。所以一般情况 这里反射的类都应该有一个共同的接口(或者说有一个共同的父类);
这样就能很明确的创建和使用由反射得来的实体类了

//接口
namespace Company.BigProgram.BLL
{
    public interface ITest
    {
        void say(string name);
    }
}
//具体实现类
namespace Company.BigProgram.BLL
{
    public class TestClass:ITest
    {
        public void say(string name)
        {
            Console.WriteLine("看这里");
        }
    }
}
//结果输出            
string className = "ImageTest.TestClass";
Type type = Type.GetType(className);
if (type != null)
{
    ITest obj = Activator.CreateInstance(type) as ITest;
    bool b = obj is TestClass;
    MessageBox.Show(b.ToString());//True
}

2.根据实例和其属性名(字符串) 获取该属性

/// <summary>
/// 获取某个对象的某个属性值
/// </summary>
/// <param name="type">对象</param>
/// <param name="propName">属性名</param>
/// <returns>属性值</returns>
private string GetPropertyValue<T>(T item, string propName)
{
    Type type = item.GetType();//获取类型
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propName);
    return (propertyInfo.GetValue(item, null) ?? "").ToString();
}

3.根据实例和其方法名(字符串)获取该方法并调用

private void GetPropertyValue<T>(T item, string name,object[] paras)
{
    System.Type type = item.GetType();//获取类型
    System.Reflection.MethodInfo func = type.GetMethod(name);//获取方法
    func.Invoke(item, paras);//调用 item是调用该方法的对象,paras是参数
}

private class Person
{
    public void say()
    {
        MessageBox.Show("XXXXOOOO");
    }

    public void call(string content)
    {
        MessageBox.Show(content);
    }
}

 

 上面三种Demo都是针对提前定义好的类型和方法属性。

下面是根据提供的字段信息动态编译的方法。

string colsStr = "Age,Name,Sex,Birthday";//字段名
string[] colNames = colsStr.Split(',');
string clsName = "DynUserTable";//动态生成的类名
string ns = "MyWeb.Test";//命名空间

var propStr = "";
foreach (var c in colNames)
{
    propStr += $"       public string {c}{{set;get;}}\r\n";
}

var typeStr = $@"
namespace {ns}
{{
    public class {ns}  {{ {propStr} }}
}}";//拼接类的定义内容

//获取编译结果
var cr = new CSharpCodeProvider()
    .CompileAssemblyFromSource(new CompilerParameters(new string[] { "System.dll" }), typeStr);
//获取类型
var targetType = cr.CompiledAssembly.GetType($"{ns}.{clsName}");

 这里有一篇.NET动态编译的文章.NET中的动态编译

关于应用程序域AppDomain的使用 走近.NET AppDomain

 

说到动态编译  Emit效率更高,是通过C#直接生成IL,不过可读性较差

//动态创建程序集  
AssemblyName DemoName = new AssemblyName("DynamicAssembly");
AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName
    , AssemblyBuilderAccess.ReflectionOnly);//如果需要持久化程序集 则选择RunAndSave或Save
//动态创建模块  
ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll");
//动态创建类MyClass  
TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
//动态创建字段  
FieldBuilder fb = tb.DefineField("myField", typeof(string), FieldAttributes.Private);
//动态创建构造函数(一个参数)
Type[] clorType = new Type[] { typeof(string) };
ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType);
//生成 Microsoft 中间语言 (MSIL) 指令(将构造函数的参数赋给字段fb)
ILGenerator ilg = cb1.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Stfld, fb);
ilg.Emit(OpCodes.Ret);
//动态创建属性
PropertyBuilder pb = tb.DefineProperty("MyProperty", PropertyAttributes.HasDefault, typeof(string), null);
//动态创建方法
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
MethodBuilder myMethod = tb.DefineMethod("get_Field", getSetAttr, typeof(string), Type.EmptyTypes);
//生成指令(方法返回fb)
ILGenerator numberGetIL = myMethod.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fb);
numberGetIL.Emit(OpCodes.Ret);
//使用动态类创建类型
Type classType = tb.CreateType();

相关文章

说说emit(上)基本操作,


 

 

 

 

转载于:https://www.cnblogs.com/TiestoRay/p/2605485.html

相关文章:

  • vim/vi卡死
  • ECSHOP修改后台地址
  • WebCast听课录(5)
  • 数字音乐维权联盟首次出招 QQ音乐起诉酷我索赔千万
  • Pure-ftpd无法连接到服务器 425错误
  • 华为交换机ntp设置
  • 同源策略
  • 硬盘驱动器
  • Powershell 修改AD用户属性
  • Unicode和多字节的相互转换
  • 基于C++任意点数的FFT/IFFT(时域和频域)实现
  • 第 19 章 Class
  • 双击防止网页放大缩小HTML5
  • 多种方式求阶乘
  • 开发android App干坏事(二)-wifi控制
  • Cumulo 的 ClojureScript 模块已经成型
  • es6要点
  • export和import的用法总结
  • Github访问慢解决办法
  • HTML中设置input等文本框为不可操作
  • JavaScript HTML DOM
  • laravel with 查询列表限制条数
  • Mysql5.6主从复制
  • React的组件模式
  • Redash本地开发环境搭建
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Spark RDD学习: aggregate函数
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Yii源码解读-服务定位器(Service Locator)
  • 创建一种深思熟虑的文化
  • 记录一下第一次使用npm
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 那些年我们用过的显示性能指标
  • 容器服务kubernetes弹性伸缩高级用法
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 鱼骨图 - 如何绘制?
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​MySQL主从复制一致性检测
  • ​渐进式Web应用PWA的未来
  • ​你们这样子,耽误我的工作进度怎么办?
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (搬运以学习)flask 上下文的实现
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)计算机毕业设计ssm电影分享网站
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (十六)Flask之蓝图
  • (十六)串口UART
  • (一一四)第九章编程练习
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • .NET Framework .NET Core与 .NET 的区别