需求
在调用某一个类的接口时,加一个泛型,只要改变泛型的类型,就能随意切换不同的接口,这个能做到么?其实也不难,下面是实现方法
代码
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