非科班出身对这些不常用到的知识很好奇,今天有空,研究下。
个人理解反射就是不直接通过namespace或者class 获取到想要的class然后操作它
形象点说就是,通常我们引用某程序集的方式有点像指腹为婚 ,你刚懂事你妈就告诉你,邻村的小凤将来是你的媳妇儿,你找她的方法就是骑着你的forever到她的村头 叫她的名字
优点:你不会光棍、你会很快生小孩、你很了解她、不了解就问你妈
缺点:你想起了楚门
映射呢,就可以理解为自由恋爱了,春天到了你需要一个女朋友 ,你有一些要求:女,长发,胸大,你找她的方式就是爬到山顶,眯着眼睛,你略带拘谨的目光扫过附近的所有村庄,你有可能一下子无法找到她,也可能找不到
优点:自由恋爱
缺点:你要花很多时间去寻找、有可能找不到、你对姑娘不是特别了解
在网上看到一个比较实际的例子,就是播放器支持的格式,你开发了一个播放器,目前只支持MP4,你没有更多精力去开发其他格式的支持,但是你留了一个插件接口给别人,别人就可以开发插件来支持其他格式,知道用处才有方向。
写播放器当然超出我的能力了。。
我假设了一个类似的场景:
字符串加密,比如你开发了一个日记累的应用,你主动把用户日记加密存储,但是小陈对你的加密方式并不放心,他希望他可以自定义一套加密方式,在保存的时候用
构想:
1.用户上传dll ,在他保存的时候调用他的dll
2.为了保证无论用户什么加密都可以得到加密结果字符串,需要限定加密方法名、参数、返回值,就是做一个接口
interface 加密接口{
string GetEncodeString(string str);
}
3.用户下载这个接口dll,引用并继承
public class 客户a的加密类:加密接口
{
public 客户a的加密类(){}
public string GetEncodeString(string str){
/****加密str****/
return str;
}
}
4.后台处理、调用客户加密
System.Reflection.Assembly ass = Assembly.LoadFrom(dll保存路径); //加载DLL
System.Type t = ass.GetType("客户a的加密类");//获得类型
object o = System.Activator.CreateInstance(t);//创建实例
System.Reflection.MethodInfo mi = t.GetMethod("GetEncodeString");//获得方法
mi.Invoke(o, new object[] { ****});//调用方法
实现:
以上是大体思路以及一些伪代码,有一点不太靠谱的是用户直接上传通过路径调用,在我最开始的想法是第三方根据接口开发dll,我作为开发者加载此dll,至于如何调用就成了一个尴尬的问题了,我的设计是客户提交信息时告诉我要调用的dll,然后通过反射查找所有实现interface的Assembly(程序集),然后查找到指定的class,为了定位到type同时不限制class的名字,限制接口增加了一个codeType属性,通过属性确定type,代码如下:
接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StringOpertor
{
public interface IStringEncode
{
/// <summary>
/// 扩展类必须声明其类名(供映射获取)
/// </summary>
string codeType { get; }
/// <summary>
/// 扩展类必须实现本接口的功能函数
/// </summary>
/// <returns></returns>
string StringEncode(string formerStr);
}
}
客户的实现
using System.Security.Cryptography;
namespace StringOpertor
{
/// <summary>
/// 字符串加工类
/// </summary>
public class StringMaker:IStringEncode
{
public StringMaker()
{
}
//
//接口属性
private string _codeType="MD5";
public string codeType
{
get{
return _codeType;
}
}
/// <summary>
/// 接口函数:字符串加密MD
/// </summary>
/// <param name="formerStr">原字符串</param>
/// <returns>加工后的字符串</returns>
public string StringEncode(string formerStr) {
//字符串处理
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bytValue, bytHash;
bytValue = System.Text.Encoding.UTF8.GetBytes(formerStr);
bytHash = md5.ComputeHash(bytValue);
md5.Clear();
string sTemp = "";
for (int i = 0; i < bytHash.Length; i++)
{
sTemp += bytHash[i].ToString("X").PadLeft(2, '0');
}
return sTemp.ToLower();
}
}
}
调用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
namespace 反射研究
{
class StringEncoder
{
public StringEncoder() { }
public string GetEncodeString(string codeType, string formerStr)
{
HttpContext c = HttpContext.Current;
string returnValue = null;
//获取类型信息(依据接口参数)
System.AppDomain _Domain = System.AppDomain.CurrentDomain;
Assembly[] _AssemblyList = _Domain.GetAssemblies();
for (int i = 0; i != _AssemblyList.Length; i++)
{
//获取程序集
Assembly ass = _AssemblyList[i];
//获取程序集的所有类
Type[] types = ass.GetTypes();
for (int j = 0; j != types.Length; j++)
{
Type type = types[j];
//根据是否实现接口IStringEncode筛选
if (type.GetInterface("StringOpertor.IStringEncode") != null)
{
PropertyInfo p = type.GetProperty("codeType");
if (p == null || !p.CanRead)
continue;
try
{
//构造器的参数
object[] constuctParms = new object[] { codeType };
//根据类型创建对象
object dObj = Activator.CreateInstance(type, null);
object className = p.GetValue(dObj, null);
if (codeType == className.ToString())
{
//获取方法的信息
MethodInfo method = type.GetMethod("StringEncode");
//调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
//GetValue方法的参数
object[] parameters = new object[] { formerStr };
//调用方法,用一个object接收返回值
returnValue = method.Invoke(dObj, flag, Type.DefaultBinder, parameters, null).ToString();
return returnValue;
}
}
catch (Exception ex)
{
}
}
}
}
return null;
}
}
}
显示
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="反射研究.Index" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
加密类型:<asp:TextBox ID="d_codeType" runat="server"></asp:TextBox>
加密字符串:<asp:TextBox ID="d_formerStr" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="加密" OnClick="Button1_Click" />
结果:<asp:Label ID="d_result" runat="server" Text="Label"></asp:Label>
</div>
</form>
</body>
</html>
using System;
namespace 反射研究
{
public partial class Index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
string codeType = d_codeType.Text;
string formerStr = d_formerStr.Text;
StringEncoder se = new StringEncoder();
string result = se.GetEncodeString(codeType, formerStr);
d_result.Text = result;
}
}
}