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 这个接口,所以是不允许调用的,这里你还可以测试一下,给构造函数加个参数,看看泛型约束,到底有没用效果。

关于泛型相关的知识点,有兴趣的可以看我的另一篇文章,这里面有详细的介绍

C# 泛型详解(泛型类,方法,接口,委托,约束,反射 )_熊思宇的博客-CSDN博客

end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值