当前位置: 首页 > news >正文

C# 用泛型和反射实现对象管理

需求

在调用某一个类的接口时,加一个泛型,只能改变泛型的类型,就能随意切换不同的接口,这个能做到么?其实也不难,下面是实现方法

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    class Program
    {
        static void Main(string[] args)
        {
            Test test = new Test();
            test.Print<Dog>().Run();
            test.Print<Cat>().Run();

            Console.ReadKey();
        }
    }

    public class Test
    {
        private Dictionary<string, object> ObjectDictionary = new Dictionary<string, object>();

        public T Print<T>() where T : class, Move, new()
        {
            Type t = typeof(T);
            string fullName = t.FullName;
            if (ObjectDictionary.ContainsKey(fullName))
            {
                return (T)ObjectDictionary[fullName];
            }
            else
            {
                object obj = Activator.CreateInstance(t);
                ObjectDictionary.Add(fullName, obj);
                return (T)obj;
            }
        }
    }

    //接口
    public interface Move
    {
        void Run();
    }

    public class Dog : Move
    {
        public void Run()
        {
            Console.WriteLine("狗跑了");
        }
    }

    public class Cat : Move
    {
        public void Run()
        {
            Console.WriteLine("猫跑了");
        }
    }

    public class Chook
    {
        public void ChickenFlew()
        {
            Console.WriteLine("鸡飞了");
        }
    }
}

运行后

来看看实现的过程

首先是定义了一个接口


public interface Move
{
    void Run();
}

然后由 dog 类和 Cat 类实现了这两个接口,这里使用一个父类也是可以的,我只是觉得接口的局限性(权限)会更加严格一些,至于为什么要实现这个接口呢?主要是为了泛型约束,在框架设计中,逻辑一旦复杂起来,就不要什么方法都对外开放了,项目的人多了,你就知道好处了。

public class Dog : Move
{
    public void Run()
    {
        Console.WriteLine("狗跑了");
    }
}

public class Cat : Move
{
    public void Run()
    {
        Console.WriteLine("猫跑了");
    }
}

至于 Chook 这个类,暂时别管他了,后面留着测试泛型约束用的

public class Chook
{
    public void ChickenFlew()
    {
        Console.WriteLine("鸡飞了");
    }
}

Test 这个类有一个字段,和一个方法,ObjectDictionary 这个字段主要作用是存储那个实例化的类,在下次调用的时候,就没必要重新实例化了。

public class Test
{
    private Dictionary<string, object> ObjectDictionary = new Dictionary<string, object>();

    public T Print<T>() where T : class, Move, new()
    {
        Type t = typeof(T);
        string fullName = t.FullName;
        if (ObjectDictionary.ContainsKey(fullName))
        {
            return (T)ObjectDictionary[fullName];
        }
        else
        {
            object obj = Activator.CreateInstance(t);
            ObjectDictionary.Add(fullName, obj);
            return (T)obj;
        }
    }
}

重点在 Print 这个方法,可以看到,它的泛型和返回值都是 T ,这里做了一个 泛型约束,

class 是指 T 必须是引用类型,

Move 是指 T 要么是 Move 类型,要么继承于 Move 这个接口,

new() 是指 T 必须是一个无参数的构造函数,

Type t = typeof(T) 是获取了泛型的 Type 类型,t.FullName 是获取了 命名空间.类名 这样的一个字符串,用来作为字典的 key,后面就是判断当前的 类名是否包含在 ObjectDictionary 中了,如果包含在 ObjectDictionary 里面,直接返回实体对象就行了

return (T)ObjectDictionary[fullName];

如果不包含,那么就用反射直接实例化对象,然后添加到 ObjectDictionary 里面,然后再返回对象,这个逻辑就是这个样子。

接下来测试一下,上面提到的 Chook 这个类,由于没用实现 Move 这个接口,所以是不允许调用的,这里你还可以测试一下,给构造函数加个参数,看看泛型约束,到底有没用效果。

end

相关文章:

  • 剑指offer32-42字符串数组的应用
  • SSM+文达学院贫困生认定系统 毕业设计-附源码261621
  • 单片机上的操作系统
  • Linux-10-线程
  • BP神经网络算法基本原理,bp神经网络算法的优点
  • 模块加载机制(require)--内置、第三方、自定义、文件夹
  • js分组匹配、遍历结果
  • shell脚本学习笔记2
  • STM32-串口通信波特率计算以及寄存器的配置详解
  • 物联网开发笔记(5)- 使用Wokwi仿真树莓派Pico实现LED灯交替闪烁(续)
  • 洛谷 P7302 [NOI1998] 免费的馅饼
  • Docker基础-2.常用命令与Docker镜像
  • Java的Lambda表达式学习笔记:认识lambda表达式
  • SAP Spartacus 项目开发时需要注意的一些常见错误
  • SpringBoot - @JsonIgnore和@JsonIgnoreProperties注解详解以及区别
  • Druid 在有赞的实践
  • ES6之路之模块详解
  • Invalidate和postInvalidate的区别
  • Java 多线程编程之:notify 和 wait 用法
  • JavaScript-Array类型
  • JavaScript类型识别
  • Java教程_软件开发基础
  • Just for fun——迅速写完快速排序
  • laravel 用artisan创建自己的模板
  • Laravel 中的一个后期静态绑定
  • Lucene解析 - 基本概念
  • MYSQL 的 IF 函数
  • October CMS - 快速入门 9 Images And Galleries
  • Travix是如何部署应用程序到Kubernetes上的
  • 从零开始在ubuntu上搭建node开发环境
  • 订阅Forge Viewer所有的事件
  • 翻译--Thinking in React
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 2017年360最后一道编程题
  • 如何正确理解,内页权重高于首页?
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (十八)SpringBoot之发送QQ邮件
  • (一)RocketMQ初步认识
  • (转)scrum常见工具列表
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @AutoConfigurationPackage的使用
  • [20170705]diff比较执行结果的内容.txt
  • [3300万人的聊天室] 作为产品的上游公司该如何?
  • [AutoSAR 存储] 汽车智能座舱的存储需求
  • [BT]BUUCTF刷题第4天(3.22)
  • [C++]Leetcode17电话号码的字母组合
  • [ffmpeg] 定制滤波器