程式集載入與反射(二):例項篇

K戰神發表於2015-06-30

目錄:

一、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 = "K-Json@139.com";
                            string to = "Wold@139.com";
                            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[]{"K-Json@139.com", "Wold@139.com","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);                

相關文章