• .Net 反射


    .Net 反射

    反射反射,程序员的快乐

    说明

    在一些常见的服务中,我们知道某些方法的名字,想要直接调用如何去做呢?
    目前我知道的是委托和反射。但是委托出现了新的方法,还得手动去添加,反射则不一样了。
    只要方法名规律保持一致,直接调用反射方法即可避免写无聊的逻辑。
    当然,反射debug有些些许麻烦

    获得实体的属性名称

       foreach (PropertyInfo propertyInfo in typeof(实体).GetProperties()) 
                {
                    fields.Add(propertyInfo.Name);
                }
    

    实体获得属性值

     var temp = 实体.GetType().GetProperty("属性").GetValue(实体, null);
    

    实体赋值

    • 反射赋值遇到类型不一致,Object of type 'System.String' cannot be converted to type 'System.Int32
      • 解决
        property.SetValue(obj,Convert.ChangeType(value,property.PropertyType),null);//类型转换。

    实体获取字段值

    C#当中获取属性有种情况为,该属性没有get和set函数,则该属性非属性,实际为字段。因此需要使用以下方法来获取:

    实体.GetType().GetFields() //查看有几个字段
    实体.GetType().GetField("字段") //不为null则存在该字段
    实体.GetType().GetField("字段").GetValue(实体) //获取字段值
    

    获取私有方法

     class Program
        {
           
            private static void Main(string[] args)
            {
                //通过反射来调私有的成员
                Type type = typeof(Person);
                //BindingFlags类型枚举,BindingFlags.NonPublic | BindingFlags.Instance 组合才能获取到private私有方法
                MethodInfo methodInfo = type.GetMethod("SayHello", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                object obj = Activator.CreateInstance(type);  //通过反射类型创建实例对象
                methodInfo.Invoke(obj, null);
    
                Console.ReadKey();
            }
        }
    
        public class Person
        {
            private static  void SayHello()
            {
                Console.WriteLine("我是私有方法。");
                Console.ReadKey();
            }
        }
    

    创建实体

    • 无构造函数 object obj = Activator.CreateInstance(type); //通过反射类型创建实例对象
    • 指定的构造函数,例如需要一个参数的构造函数。var client = Activator.CreateInstance(tmpType,new object[] { channel });

    异步方法

    • invoke 转换为Task类型,await 等待完成,接着反射Task.Result的值
                var type = this.GetType();
                var methodList = type.GetMethods().Where(a => a.Name.StartsWith("GetExport") && a.Name.EndsWith("List")).ToList();
                foreach (var method in methodList)
                {
                    var task = (Task)method.Invoke(this, null);
                    await task;
                    var val = task.GetType().GetProperty("Result").GetValue(task, null) as IEnumerable<object>;
                    if (val != null)
                        workBook.Write(DisplayAttributeHelper.GetTable(val.ToList()));
                }
    

    泛型方法

    • GetMethod获取泛型方法名称, MakeGenericMethod写入指定类型的参数(Type类型)。最后Invoke
                    string binPath = Assembly.GetExecutingAssembly().Location;
                    var assembly = Assembly.LoadFrom(binPath); //反射看这篇文章  https://www.cnblogs.com/zagelover/articles/2726034.html
                    var allServiceList = assembly.GetTypes().Where(a => a.Namespace.StartsWith("DataTool.gRPC.Service")
                    &&a.Name.EndsWith("Service")).ToList();
                    allServiceList.ForEach(a =>
                    {
                        var method = typeof(GrpcEndpointRouteBuilderExtensions).GetMethod("MapGrpcService").MakeGenericMethod(a);
                        method.Invoke(null, new[] { endpoints });
                    });
    

    静态类和非静态类

    • 静态类Invoke(null, new[] { endpoints }); todo 等待补充
    • 非静态类Invoke(this, null)

    特性

    • CustomAttributes属性中的 AttributeType等于typeof(ObsoleteAttribute)
                //反射特性
                string binPath = Assembly.GetExecutingAssembly().Location;
                var assembly = Assembly.LoadFrom(binPath); //反射看这篇文章  https://www.cnblogs.com/zagelover/articles/2726034.html
                var methodList= assembly.GetType("DataTool.Demo.Program").GetMethods().ToList();
                var a1 = methodList.FirstOrDefault(a => a.Name == "Task1");
                //var b1 = a1.GetCustomAttribute<ObsoleteAttribute>();
                var aaa1= a1.CustomAttributes.Any(a => a.AttributeType ==typeof(ObsoleteAttribute));
    
    • 获取特性值

    加载程序集

    var assembly = Assembly.Load("DataTool.Model");

    创建List<泛型>

    • 通过反射创建List泛型的话,后面只能通过反射该对象的方法去做。
                 //创建List泛型对象结果,也可以通过反射实现`AddRange`,这边采用.ToList()
                //https://www.cnblogs.com/lovewl2/p/6582347.html
                //var result = (Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { entityType })) as IEnumerable<object>).ToList();
    
    • 可以直接var result = new List<object>();

    .net core 依赖注入gRPC服务

    • 原本注入方式
                //先注入一个Mi服务实施
                services.AddTransient(a =>
                {
                    var zz = a;
    
                    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
                    var baseGRPCUrl = AppSettingsHelper.Configuration["GRPCUrl"];
                    var channel = GrpcChannel.ForAddress(baseGRPCUrl);
                    return new MI.MIClient(channel);
                });
    
    • 反射注入。先注入构造函数所需对象,再注入构造函数的对象。
                //反射注入所有服务
                var assembly = Assembly.GetExecutingAssembly();
                var serviceList = assembly.GetTypes().Where(a => a.Namespace==("DataTool.WebApi.Controllers")
                &&a.GetMembers().Any(b=>b.Name.EndsWith("Client"))
                ).ToList(); //https://q.cnblogs.com/q/67716/  GetMembers
    
                AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
                var baseGRPCUrl = AppSettingsHelper.Configuration["GRPCUrl"];
                var channel = GrpcChannel.ForAddress(baseGRPCUrl);
                //先注入gRPC构造函数所需对象
                services.AddTransient(a => {
                    return channel;
                });
                serviceList.ForEach(a =>
                {
                    var tmpType = a.GetMembers().First(b => b.Name.EndsWith("Client")) as Type;
                    var client = Activator.CreateInstance(tmpType,new object[] { channel });
                    services.AddTransient(tmpType,q1=> { return client; });
                });
    
  • 相关阅读:
    关于【无法将*.dll复制到指定目录】错误的解决
    给一个容器控件内(如:div,form)文本框批量添加验证事件
    js操作dom(2)
    关于.net中修饰符的一点总结
    js操作dom(3)
    关于【源文件与模块生成时的文件不同】问题的解决
    pb中用OLE Control 报错解决方法 (转载)
    Web前端技术(摘抄)
    Uva1420 Priest John's Busiest Day
    UVa1445 Cubist Artwork
  • 原文地址:https://www.cnblogs.com/Alex-Mercer/p/15513709.html
Copyright © 2020-2023  润新知