目錄:
- 上篇:程式集載入與反射(一):基礎篇
- Demo:下載
一、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);