程序集加载与反射(二):实例篇

目录:

一、Demo

下面这个Demo,使用了策略模式模仿了一下插件机制。我们举个一邮件发送的例子:

1、一个策略类库:Strategy,里面定义了邮件需要实现的接口:IEmailStrategy.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Strategy
{
    public interface IEmailStrategy
    {
        string From { get; }
        string To { get;  }
        string Subject { get; }
        bool Send(string from, string to, string subject);
    }
}

2、一个具体实现类库:Target,具体的邮箱发送策略实现:Tow_Email.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Strategy;

namespace Target_1
{
    public class Email : IEmailStrategy
    {
        public string TestField_1 = string.Empty;
        public int TestField_2 = 0;

        public Email(string from, string to, string subject)
        {
            _from = from;
            _to = to;
            _subject = subject;
        }
        private readonly string _from;
        private readonly string _to;
        private readonly string _subject;
        public string From
        {
            get { return _from; }
        }
        public string To
        {
            get { return _to; }
        }
        public string Subject
        {
            get { return _subject; }
        }

        public bool Send(string from, string to, string subject)
        {
            Console.WriteLine("Send Email Successed ! ");
            return true;
        }

    }
}

3、最后我的宿主程序,ReflectionTest,将具体的邮箱策略实现 Target_1.dll (可以看作第三方代码)dll拷贝到,宿主程序相关目录下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //获取当前主程序所在路径
            string hostFilePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
            //获取dll路径
            string[] dlls = System.IO.Directory.GetFiles(hostFilePath, "*.dll");

            foreach (string dll in dlls)
            {
                //加载dll
                System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(dll);

                if (assembly != null && assembly.GetName().Name == "Target_1")
                {
                    Console.WriteLine("Assembly name:{0}", assembly.FullName);

                    //获取程序集中所有公共类
                    Type[] types = assembly.GetExportedTypes();

                    foreach (Type t in types)
                    {
                        Console.WriteLine("Type name :{0}", t.FullName);

                        if (t.IsClass && typeof(Strategy.IEmailStrategy).IsAssignableFrom(t))
                        {
                            //获取当前类中公共成员
                            System.Reflection.MemberInfo[] members = t.GetMembers();

                            string from = "[email protected]";
                            string to = "[email protected]";
                            string subject = "Come on baby";

                            Console.WriteLine("----实例化----");
                            Strategy.IEmailStrategy email = (Strategy.IEmailStrategy)System.Activator.CreateInstance(t, from, to, subject);
                            if (email != null)
                            {
                                string _f=email.From;
                                string _t=email.To;
                                string _s=email.Subject;
                                email.Send(_f,_t,_s);
                            }

                            //字段
                            Console.WriteLine("----字段----");

                            System.Reflection.FieldInfo[] fields = t.GetFields();

                            foreach (var f in fields)
                            {
                                Console.WriteLine("Field  name : {0}", f.Name);

                                Console.WriteLine("Field  type : {0}", f.FieldType.ToString());

                                Console.WriteLine("Field  value : {0}", f.GetValue(email).ToString());
                            }

                            //属性
                            Console.WriteLine("----属性----");

                            System.Reflection.PropertyInfo[] ppinfo = t.GetProperties();

                            foreach (var p in ppinfo)
                            {
                                Console.WriteLine("PropertyInfo name: {0}", p.Name);

                                Console.WriteLine("PropertyInfo can read: {0}", p.CanRead.ToString());

                                Console.WriteLine("PropertyInfo can write: {0}", p.CanWrite.ToString());

                                Console.WriteLine("PropertyInfo value: {0}", p.GetValue(email));
                            }

                            //方法
                            Console.WriteLine("----方法----");

                            System.Reflection.MethodInfo[] methodsinfo = t.GetMethods();

                            foreach (var mt in methodsinfo)
                            {
                                Console.WriteLine("MemberInfo name: {0}", mt.Name);
                                object[] objs=new object[]{"[email protected]", "[email protected]","Come on baby!"};

                                if(mt.Name=="Send")
                                mt.Invoke(email,objs);

                                //全能方法:此处正是执行了一下方法
                                t.InvokeMember("Send",System.Reflection.BindingFlags.InvokeMethod, null, email, objs);
                            }
                            Console.ReadKey();
                        }
                    }
                }
            }
        }
    }
}

总结:

1、常规反射

加载程序集  --->  筛选类 GetExportedTypes()  ---> 实例化(System.Activator.CreateInstance)  ---> 获取类公共成员 GetMembers()  ---> Type类的:GetFields(),GetProperties(),GetMethods()

2、全能反射:InvokeMember("Send",System.Reflection.BindingFlags.InvokeMethod, null, email, objs);

时间: 2024-12-26 17:28:08

程序集加载与反射(二):实例篇的相关文章

第23章 程序集加载和反射

程序集加载和反射,实现了在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息,创建类型的实例以及访问类型的成员.显现的功能以及效果是十分强大的,比如使用第三方提供的程序集,以及创建动态可扩展应用程序. 23.1 程序集加载 JIT编译器在将方法的IL代码编译成本地代码时,会查看IL代码中引用了哪些类型.在运行时,JIT编译器查看元数据表TypeRef和AssemblyRef来确定哪一个程序集定义了所引用的类型.在AssemblyRef元数据表的记录项中,包含了构成程序集强名称的各个部分

clr via c# 程序集加载和反射(2)

查看,clr via c# 程序集加载和反射(1) 8,发现类型的成员: 字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性. MemeberInfo的派生列表: System.Reflection.MemberInfo    System.Reflection.EventInFo System.Reflection.FieldInfo    System.Reflection.MethodBase          

程序集加载与反射

目录 程序集加载 获取类型信息 构造类型实例 通过反射发现成员 调用成员 一.程序集加载 Load方法:CLR通过调用System.Rreflection.Assemblly类的静态方法来显示加载程序集. public static Assembly Load(AssemblyName assemblyRef); public static Assembly Load(string assemblyString); LoadFrom方法:同样我们可以使用 远程加载程序集.此方法首先打开程序集,并

clr via c# 程序集加载和反射集(一)

1,程序集加载---弱的程序集可以加载强签名的程序集,但是不可相反.否则引用会报错!(但是,反射是没问题的) //获取当前类的Assembly Assembly.GetEntryAssembly() //通过Load方法加载程序集 Assembly.Load //通过LoadFrom加载指定路径名的程序集--可以时url对象. Assembly LoadFrom(string path) //只是反射,并确保程序集中的数据不被执行. ReflectionOnlyLoadFrom() Reflec

第二十三章 程序集加载和反射

目录: 23.1 程序集加载 23.2 使用反射构建动态可扩展应用程序 23.3 反射的性能 23.4 设计支持加载项的应用程序 23.5 使用反射发现类型的成员 23.1 程序集加载 JIT编译器将方法的IL代码编译成本机代码时,会查看IL代码中引用了哪些类型.在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所有引用的类型. 通过Assembly的Load方法加载程序集. 23.2 使用反射构建动态可扩展应用程序 23.3 反射的性能 2

程序集加载和反射

一.程序集加载 1,根据程序集名称查找程序集 public class Assembly { public static Assembly Load(AssemblyName assemblyRef); public static Assembly Load(string assemblyString); //未列出不常用的Load重载 } Assembly.Load("ConsoleApplication2");, 2,根据程序集文件路径名(包含扩展名)查找程序集 public cl

程序集加载与反射(二):实战篇

目录: 上篇:http://www.cnblogs.com/sunchong/p/4550476.html Demo 一.Demo 下面这个Demo,使用了策略模式模仿了一下插件机制.我们举个一邮件发送的例子: 1.一个策略类库:Strategy,里面定义了邮件需要实现的接口:IEmailStrategy. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sys

黑马程序员————java中类的加载、反射、动态代理、枚举

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 类的加载.反射.动态代理.枚举 一.类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 1.加载: 就是指将class文件读入内存,并为之创建一个Class对象 ★★

第一节:程序集加载

我们知道JIT编译器将方法的IL代码编译成本地代码时,会查看IL代码中引用了哪些类型.在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所引用的类型.在AssemblyRef元数据表的记录项中,包含了构成程序集强名称的各个部分.JIT编译器获取所有这些部分,包括名称(无扩展名和路径).版本.语言文化和公钥标记,并把它连接成一个字符串.然后,JIT编译器尝试将与该标识匹配的一个程序集加载到AppDomain中(如果还没有加载的话).如果被加载的