使用反射动态加载dll
//1.动态读取Dll
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
//2.获取某一个具体的类型:参数需要是类的全名称;
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
//3.创建对象
object? oInstance = Activator.CreateInstance(type); //调用无参构造函数
object? oInstance1 = Activator.CreateInstance(type, new object[] {123,"ABC"}); //调用有参构造函数,参数按照顺序放在object数组中
//4.类型转换
var MesApi = oInstance as MesApi;
// 5.调用方法
MesApi.SetValues();
动态读取Dll–三种方式
1.LoadFrom:dll全名称,需要后缀
2.LoadFile:全路径,需要dll后缀,
3.Load dll:名称 不需要后缀
反射调用静态方法
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
public ApiResult UserLogin(JObject SendData)
{
//全部参数组成数组
object[] args = new object[] { "A301", SendData };
Type type1 = assembly.GetType("EVEDAS.UPDLL.Api.A300");
return (ApiResult)type1.InvokeMember("Execute", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, null, args);
}
使用dynamic 作为类型的声明,在调用的时候,没有限制
dynamic dInstance = Activator.CreateInstance(type);
dInstance.SetValues();
dynamic 是动态类型,它不在编译时决定类型而是运行时决定是什么类型,会避开编译器的检查;
通过反射破坏单例
反射动态记载dll,元数据中只要有的不论是私有或共有,都可以给找出来。不用关注权限问题,反之私有化成员只能从内部访问。
反射调用方法(直接调用不做类型转换)
步骤1.获取方法MethodInfo
步骤2.执行MethodInfo 的Invoke方法,传递方法所在的类的实例对象+参数
调用无参数的方法
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
object oInstance = Activator.CreateInstance(type);
MethodInfo show = type.GetMethod("ShowTest");
show.Invoke(oInstance, new object[] { }); //无参数方式一
show.Invoke(oInstance, new object[0]);//无参数方式二
show.Invoke(oInstance, null);//无参数方式三
调用有参数的方法(重载方法)
需要通过方法参数类型类区别方法,传递参数需要匹配参数类型
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
object oInstance = Activator.CreateInstance(type);
MethodInfo show2 = type.GetMethod("ShowTest");
show2.Invoke(oInstance, new object[] { 123 });
MethodInfo show3 = type.GetMethod("ShowTest", new Type[] { typeof(string), typeof(int) });
show3.Invoke(oInstance, new object[] { "测试输入", 234 });
调用私有方法
在获取方法的时候,加上参数BindingFlags.NonPublic | BindingFlags.Instance
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
object oInstance = Activator.CreateInstance(type);
MethodInfo show4 = type.GetMethod("ShowTest",BindingFlags.NonPublic | BindingFlags.Instance);
show4.Invoke(oInstance, new object[] { 123 });
调用泛型方法
获取到方法后,先确定类型,严格按照参数类型传递参数就可以正常调用 。 泛型是延迟声明,调用的时候,才确定类型。
//1.调用泛型方法
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
object oInstance = Activator.CreateInstance(type);
MethodInfo show = type.GetMethod("Show");
//泛型方法,先设置泛型方法的类型
MethodInfo genericshow = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
genericshow.Invoke(oInstance, new object[] { 123, "测试", DateTime.Now });
//2.调用泛型类
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
Type generType = type.MakeGenericType(new Type[] { typeof(int) });
object oInstance = Activator.CreateInstance(generType);
//泛型类,设置泛型类的类型
MethodInfo show = generType.GetMethod("Show");
//泛型方法,先设置泛型方法的类型
MethodInfo genericMethod = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
genericMethod.Invoke(oInstance, new object[] { 123, "测试", DateTime.Now });
反射调用字段属性
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +@"\EVEDAS.UPDLL.dll");
Type type = assembly.GetType("EVEDAS.UPDLL.Api.A300");
object oInstance = Activator.CreateInstance(type);
foreach (var prop in type.GetProperties())
{
if (prop.Name.Equals("Id"))
{
//设置属性
prop.SetValue(oInstance, 134);
}
else if (prop.Name.Equals("Name"))
{
//获取属性
prop.GetValue(oInstance);
}
}