本文简单介绍如何动态创建接口interface的实现实例对象,包含两个知识点:

1.如何获取接口interface的所有实现实例对象?

2.如何判断实例对象的构造函数是否有参数?

准备工作

  首先新建一个名为IAnimal的interface接口对象,并定义一个Cry方法。

namespace DynamicCreate
{
/// <summary>
/// 动物
/// </summary>
public interface IAnimal
{
/// <summary>
/// 叫
/// </summary>
public void Cry();
}
}

  然后,我们分别新建一个Dog,Cat对象,并分别实现Cry方法。

  其中,Dog的构造函数中包含一个名为name的参数。

namespace DynamicCreate
{
/// <summary>
/// 狗
/// </summary>
public class Dog : IAnimal
{
/// <summary>
/// 名字
/// </summary>
private string _name { get; } /// <summary>
/// 有参构造函数
/// </summary>
/// <param name="name">狗名</param>
public Dog(string name)
{
_name = name;
} /// <summary>
/// 狗叫
/// </summary>
public void Cry()
{
Console.WriteLine($"{_name}汪汪汪");
}
}
}

  Cat的构造函数则为无参构造函数。

namespace DynamicCreate
{
/// <summary>
/// 猫
/// </summary>
public class Cat : IAnimal
{
/// <summary>
/// 无参构造函数
/// </summary>
public Cat()
{ } /// <summary>
/// 猫叫
/// </summary>
public void Cry()
{
Console.WriteLine("喵喵喵");
}
}
}

  常规的调用方法如下所示。

IAnimal animal_Dog = new Dog("旺财");
animal_Dog.Cry();
IAnimal animal_Cat = new Cat();
animal_Cat.Cry();

  运行结果如图所示

  如果我们想要一次性将所有实现了IAnimal接口对象Cry方法的实例全部执行一遍,只能一个对象一个对象的初始化,然后调用cry方法。这样太麻烦,我们可以通过动态创建对象并执行对象的方法来实现这个效果。   

下面,我们将开始动态创建所有实现。第一步,我们需要先获取到所有实现了IAnimal实例对象。

1.如何获取接口interface的所有实现实例对象?

  通过反射来获取当前项目中的程序集对象列表,并根据程序集对象的类型来获取继承或实现了IAnimal接口的对象列表。

//获取实现接口IAnimal的实例对象
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IAnimal))))
.ToList(); 

  我们将结果打印出来看一下

foreach (Type t in types)
{
Console.WriteLine(t.Name);
}

  

  现在,我们已经得到了所有实现IAnimal接口的实例对象。讲道理来说,我们就可以用Activator动态创建这些对象了。我们可以使用下面的代码来实现批量动态创建对象。

foreach (Type t in types)
{
var animal = (IAnimal)Activator.CreateInstance(t)!;
animal.Cry();
}

  然而,却出现一个错误提示:Dog不包含一个无参构造函数。

  所以,创建时需要将Dog的构造函数参数name传递进去,如下所示。

foreach (Type t in types)
{
var animal = (IAnimal)Activator.CreateInstance(t, new object[] { "阿黄" })!;
animal.Cry();
}

  然而,再次提示:Cat的构造函数不存在。

  这是因为Cat不包含一个带参数的构造函数,所示无法初始化Cat对象。所以,我们需要判断对象是否是有参构造函数或无参构造函数。

2.如何判断实例对象的构造函数是否有参数?

  我们可以通过GetConstructors方法来获取对象的构造函数集合,并通过GetParameters方法获取到构造函数的参数集合,判断构造函数的参数集合是否为空即可判断该对象的构造函数是否为有参或无参构造函数。

foreach (Type v in types)
{
if (v.GetConstructors().Any(x => x.GetParameters().Any()))
{
Console.WriteLine($"{v.Name}=>有参构造函数");
}
else
{
Console.WriteLine($"{v.Name}=>无参构造函数");
}
}

  

  现在,我们可以愉快的创建对象,并调用对象的方法了。

foreach (Type t in types)
{
IAnimal animal;
if (t.GetConstructors().Any(x => x.GetParameters().Any()))
{
//有参构造函数
//动态创建IAnimal的有参构造函数实现实例对象Dog
animal = (IAnimal)Activator.CreateInstance(t, new object[] { "阿黄" })!;
}
else
{
//无参构造函数
//动态创建IAnimal的无参构造函数实现实例对象Cat
animal = (IAnimal)Activator.CreateInstance(t, new object[] { })!;
}
animal.Cry();
}

  

  最后,附上完整代码,请大神们不要喷我

  GitHub

  码云

C#动态创建接口的实现实例对象的更多相关文章

  1. Java中如何动态创建接口的实现

    有很多应用场景,用到了接口动态实现,下面举几个典型的应用: 1.mybatis / jpa 等orm框架,可以在接口上加注解进行开发,不需要编写实现类,运行时动态产生实现. 2.dubbo等分布式服务 ...

  2. C#动态创建单例类的对象

    单例类 public class SnappingClass : ISnappingEnvironment, IExtension { // private static readonly Snapp ...

  3. 【转】FMX 动态创建及销毁(释放free)对象

    http://www.2pascal.com/thread-3037-1-1.html这是原文地址. (* ********************************************** ...

  4. FMX 动态创建 和 销毁(释放free) 对象

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  5. Vue动态创建注册component的实例代码

    https://segmentfault.com/a/1190000015698278

  6. .Net 中的反射(动态创建类型实例) - Part.4

    动态创建对象 在前面节中,我们先了解了反射,然后利用反射查看了类型信息,并学习了如何创建自定义特性,并利用反射来遍历它.可以说,前面三节,我们学习的都是反射是什么,在接下来的章节中,我们将学习反射可以 ...

  7. .Net 中的反射(动态创建类型实例)

    动态创建对象 在前面节中,我们先了解了反射,然后利用反射查看了类型信息,并学习了如何创建自定义特性,并利用反射来遍历它.可以说,前面三节,我们学习的都是反射是什么,在接下来的章节中,我们将学习反射可以 ...

  8. JS中new的自定义实现创建实例对象

    我们都知道在JS中通常通过对象字面量和new关键字来创建对象,那么今天我就来给大家讲讲new是怎么创建实例对象的:首先创建一个构造函数: function Person(name,age){ this ...

  9. unity3d通过代码动态创建销毁游戏对象

    只能动态创建内部提供的游戏对象,代码如下: //按下C后创建 if (Input.GetKeyDown (KeyCode.C)) { GameObject s1 = GameObject.Create ...

随机推荐

  1. 双指针之滑动窗口(长度最小的子数组 和 和为s的连续正数序列)

    双指针之滑动窗口 (长度最小的子数组:和为s的连续正数序列) 1, 什么时候使用? (与子数组/字符串 有关的题目)~如果给了某个具体值的target,即用滑动窗口 不然就双指针(一般做法,左边< ...

  2. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  3. (课内)信安数基RSA-基础&&解密加速

    RSA基本实现 首先获得N比特的伪随机数:使用Random库中内容. randint(n,m) 表示生成一个在n和m之间的随机数, **表示乘幂. getPrime找素数,or 1运算是一种优化:如果 ...

  4. UltraSoft - Beta - Scrum Meeting 6

    Date: May 22n'd, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 修复了DDL日程自动发邮件被服务器"吞掉"的bug后端增加了 ...

  5. Django+Vue跨域配置与经验

    一.原理 同源?同源策略? 同源的定义是:两个页面的协议.端口和域名都相同 同源的例子: 不同源的例子: 同源策略SOP(Same origin policy)是一种浏览器约定,它是浏览器最核心也最基 ...

  6. Spring Security 多过滤链的使用

    Spring Security 多过滤链的使用 一.背景 二.需求 1.给客户端使用的api 2.给网站使用的api 三.实现方案 方案一: 方案二 四.实现 1.app 端 Spring Secur ...

  7. 莱特币(LTC)开发环境搭建

    Linux系统下搭建莱特币LTC开发环境 1.简介 2.LTC 客户端下载 3.解压到一个固定的目录中 4.启动客户端 4.1.参数解释: 4.2.更多详细的配置 5.执行命令测试一下 6.获取莱特币 ...

  8. 文件上传漏洞Bypass总结

    文件上传漏洞Bypass总结 前端JS验证文件类型: 上传后缀jpg,抓包改为php后缀 ======================================================= ...

  9. python numpy版本报错: File "*\numpy\__init__.py", line 305, in <module> _win_os_check()

    具体代码如下所示: from numpy import * import operator a = random.rand(4, 4) print(a) 具体报错内容如下所示: Traceback ( ...

  10. c++ get keyboard event

    #include <string> #include <iostream> #include "windows.h" #include <conio. ...