dynamic中文_dynamic cast

dynamic中文_dynamic castC# 反射、与dynamic最佳组合

大家好,又见面了,我是你们的朋友全栈君。

https://www.cnblogs.com/dw039/p/7476011.html

反射最突出的优点或存在的合理性:在不修改程序原码的情况下,实现程序功能的动态调整(Runtime动态对象创建

interface IRun {

void Run();
}
class Person : IRun
{

public void Run()
{

Console.WriteLine(“走,去LOL啊!”);
}
}
class Car : IRun
{

public void Run()
{

Console.WriteLine(“呜………..”);
}
}

class Program
{

static void Main(string[] args)
{

IRun e = new Person();
e.Run();
Console.ReadLine();
}
}

如果将上面的Run功能并不一定是由Person来执行,有时需要是Car有时需要Person。常见的解决方案是添加 if 等判断结构,如下:

复制代码
       static void Main(string[] args)
        {
            Console.WriteLine("请输入:Car或Person");
            string type = Console.ReadLine();
            IRun e = null;
            if ("Car" == type)
            {
                e = new Car();
            }else if("Person" == type)
            {
                e = new Person();
            }
            if(null != e)
                e.Run();

            Console.ReadLine();
        }
复制代码

这种结构确是解决了现在的需求,但并不健壮。随着 IRun 接口实现、相关类的继承的增加,上面的判断结构也会飞速增长。面向对象编程、设计模式均遵循的一大原则就是封装变换,所以上面的程序无法很好的应对变化。在此我们并不涉及 “设计模式的” 的知识,因此下面的示例代码只为简化上面的程序、并未刻意套用设计模式相关知识。如下:

复制代码
        static void Main(string[] args)
        {
            Console.WriteLine("请输入:Car或Person");
            string type = Console.ReadLine();
            string classPath = String.Format("namespace.{0}", type);
            IRun e = Activator.CreateInstance(null, classPath).Unwrap() as IRun;

            if(null != e)
                e.Run();

            Console.ReadLine();
        }
复制代码

经过上面的修改,程序可自行根据用户的输入,通过Activator.CreateInstance创建 IRun 的实例,程序此处不会再随 IRun 的实现者增多这种问题的影响而发生变化。上面的这种优点就是通过反射得到的,也是我所认为的“反射存在的合理性”。

Activator、Assembly 实现反射方式创建对象

C#中反射方式创建对象可以通过 Activator.CreateInstance(静态)和 Assembly.CreateInstance(非静态)来实现,其中Assembly.CreateInstance 内部调用的仍是Activator.CreateInstance。

根据要动态创建的类型对象是否处于当前程序集之中,可将反射创建对象分为:创建程序集内的类型对象与创建程序集外的类型对象。

创建程序集内的类型对象

复制代码
        private static void ReflectionIRun1(string className)
        {
            string classPath = String.Format("namespace.{0}", className);
            //参数 null ,指出所要创建类型对象位于当前程序集 
            var handler = Activator.CreateInstance(null, classPath);
            IRun e = (IRun)handler.Unwrap();
            Console.WriteLine(e.Run());
        }
        private static void ReflectionIRun2(string className)
        {
            string classPath = String.Format("namespace.{0}", className);
            //typeof(IRun).Assembly 获取 IRun 类型所在的程序集
            object obj = typeof(IRun).Assembly.CreateInstance(null, classPath);
            IRun e = (IRun)obj;
            Console.WriteLine(e.Run());
        }
复制代码

创建程序集外的类型对象

项目中增加一个 类库 (另一个程序集),如下图:

dynamic中文_dynamic cast

添加一个 Boss 类,如下:

复制代码
namespace Lib
{
    public class Boss
    {
        private string name = "老大";
        
        public string Name{
            get {return name;}
        }
        public string Talk()
        {
            return "你们都被开除了......";
        }
        //老板不会算账,总是多付钱,所以很有自知之明的将Payfor设为private,防止外部人员调用
        private int Payfor(int total)
        {
            return total + 10;
        }
    }
}    
复制代码

获取 一个 Boss 对象前,首先添加对 Lib 的引用,获取示例如下:

复制代码
        private static void ReflectionBoss1()
        {
            string classPath ="Lib.Boss";
            //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
            var handler = Activator.CreateInstance("Lib", classPath);
            Boss b = handler.Unwrap() as Boss;
            Console.WriteLine(b.Talk());
        }
        private static void ReflectionBoss2()
        {
            string classPath ="Lib.Boss";
            //Assembly.Load("Lib") 加载的程序集(即要创建的对象类型在哪个程序集中定义)
            var assembly = Assembly.Load("Lib");
            Boss b = (Boss)assembly.CreateInstance(classPath);
            Console.WriteLine(b.Talk());
        }  
复制代码

关于反射时CLR如何查找并定位要加载的程序集,请参考MSDN中关于反射相关的知识。

反射访问字段、调用方法(属性

反射除可以帮我们动态创建对象外,还可帮我们动态访问对象的方法(属性)或字段,因 C# 版本不同具体方法会有变更或扩展,更深入内容请参考MSDN。下面仅作简单示例(标准用法)。

给老板改名,示例: 

复制代码
        private static void ReflectionBoss1()
        {
            string classPath = "Lib.Boss";
            //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
            var handler = Activator.CreateInstance("Lib", classPath);
            Boss b = handler.Unwrap() as Boss;
            //关键代码
            FieldInfo f = b.GetType().GetField("name", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
            f.SetValue(b, "小二");

            Console.WriteLine("{0}:{1}", b.Name, b.Talk());
        }
复制代码

输出:

dynamic中文_dynamic cast

让老板付钱:

复制代码
private static void ReflectionBoss1()
        {
            string classPath = "Lib.Boss";
            //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
            var handler = Activator.CreateInstance("Lib", classPath);
            Boss b = handler.Unwrap() as Boss;
            //关键代码
            MethodInfo method = b.GetType().GetMethod("Payfor", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance);
            object money = method.Invoke(b, new object[] { 10 });
Console.WriteLine("DW039:老大给我报销10元钱车费......"); Console.WriteLine("{0}:.....,算不清了,给你这些吧。",b.Name); Console.WriteLine("DW039:......"); Console.WriteLine("{0}:{1}", b.Name,money); Console.WriteLine("DW039:老大你真棒!"); }
复制代码

输出:

dynamic中文_dynamic cast

dynamic 与 反射 双剑合璧

因为反射是运行时的类型操作,所以在编程时面临类型不确定的问题。根据上一篇《C# 匿名对象(匿名类型)、var、动态类型 dynamic》讲得 dynamic 动态类型结合我们编写的反射程序,可以大大优化程序逻辑(访问受保护级别限制的代码不在此范围内)。

上面代码的优化:

复制代码
 private static void ReflectionBoss1()
        {
            string classPath ="Lib.Boss";
            var handler = Activator.CreateInstance("Lib", classPath);
            dynamic b = handler.Unwrap();
            Console.WriteLine(b.Talk());
        }
        private static void ReflectionBoss2()
        {
            string classPath ="Lib.Boss";
            var assembly = Assembly.Load("Lib");
            dynamic b = assembly.CreateInstance(classPath);
            Console.WriteLine(b.Talk());
        }  
复制代码

通过 dynamic 动态类型对象 b 来调用反射得到对象的属性、方法可直接调用,从而省去了频繁的类型转换操作。

反射常见应用场景

应用场景我印象最深刻的是 MS Petshop 示例,从SQL Server 数据库切换到 oracle 数据库时反射获得不同的数据访问层。然我实际项目中从未遇到过中途切换数据库的情况,其他应用场景基本类似上面的示例。如果朋友你发现更多的应用场景,请给予补充,3ks。

反射的优缺点

优点:反射使程序更灵活

缺点:反射运行速度相对较慢

至于反射相比普通程序慢,我没有进行过测试也不打算进行。现实情况是:Ms提倡使用 dynamic、Mvc流行、Ms对CLR不断优化、机器性能的提升,所以你在开发中无需过多考虑反射的性能问题。如果你写的程序运行速度出现了瓶颈(应首先确保自己程序写的合理),研究一下数据库优化、数据缓存、web缓存、负载均衡等技术我认为更实际一些。

请放心大胆的使用反射技术吧,朋友!

转载于:https://www.cnblogs.com/tsql/p/10598355.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106914.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • webstorm的永久激活码2021-激活码分享[通俗易懂]

    (webstorm的永久激活码2021)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月22日
    3.0K
  • 【用户画像】从0到1掌握用户画像知识体系

    【用户画像】从0到1掌握用户画像知识体系一、初始用户画像1.1用户画像随着用户的一切行为数据可以被企业追踪到,企业的关注点日益聚焦在如何利用大数据为经营分析和精准营销服务,而要做精细化运营,首先要建立本企业的用户画像。提到用户画像的概念,我们区分下用户角色(Persona)和用户画像(Profile):1.1.1用户角色用户角色本质是一个用以沟通的工具,当我们讨论产品、需求、场景、用户体验的时候,为了避免在目标用户理解上的分歧,用户角色应运而生。用户角色建立在对真实用户深刻理解,及高精准相关数据的概括之上,虚构的包含典型用

    2022年5月25日
    101
  • Python运维常用的脚本,提高工作效率就靠它了

    Python运维常用的脚本,提高工作效率就靠它了前言用Python做运维的小伙伴肯定会进行重复的工作,这个时候脚本的重要性就体现出来了一个好的脚本工具可以帮你省去很多重复的工作,创造更大的价值下面小编就带你们看看Python运维最常用的脚本吧清除指定redis缓存#!/usr/bin/envpython3#-*-coding:utf-8-*-#@Time:2018-12-2015:19…

    2022年7月12日
    21
  • mysql—mysql中的整数和字符串类型

    mysql—mysql中的整数和字符串类型

    2020年11月12日
    193
  • C# 哈希_java哈希码

    C# 哈希_java哈希码文件哈希码比较,用于更新文件publicstaticboolCompareFile(stringstr1,stringstr2)    {      stringp_1=str1;      stringp_2=str2;      //计算第一个文件的哈希值      varha

    2025年6月26日
    5
  • jar中没有主清单属性 (亲测有效)[通俗易懂]

    jar中没有主清单属性 (亲测有效)[通俗易懂]<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></.

    2025年9月14日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号