C#实现动态创建接口并调用的实例
作者:摇曳de风筝 发布时间:2021-11-12 16:38:17
本文简单介绍如何动态创建接口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
码云
来源:https://www.cnblogs.com/pinzi/p/15598531.html


猜你喜欢
- 最近在研究springboot实现FastJson解析json数据的方法,那么今天也算个学习笔记吧!添加jar包:<dependenc
- 一、实现效果本篇文章实现了简单的图片轮播,初始化3张资源图片,初始化3秒更换一次图片背景,轮换播放。二、知识点Thread线程start()
- 目录Profile用法resourcesfilters多环境配置解决方案Profile用法我们在application.yml中为jdbc.
- 本文实例讲述了Android编程实现等比例显示图片的方法。分享给大家供大家参考,具体如下:在android中,由于密度的影响,如果想得到图片
- Android中ImageView的使用:点击按钮,改变图片透明度,切换图片布局是三个按钮组件和一个ImageView组件<?xml
- Unity 跑马灯抽奖效果实现代码,供大家参考,具体内容如下这边用到插件是NGUI+Dotween,思路简单说下:先排版,通过移动图片蒙版来
- 日常开发中,判断邮箱是少不了的,这个我以**C#**为例,来写一个判断方法,正则表达式是通用的,CV就可以首先引入正则需要使用的命名空间//
- 本文实例讲述了C#使用foreach循环遍历数组的方法。分享给大家供大家参考,具体如下:using System;using System.
- 对于之前最火的无外乎集五福了,而五福除了加十个好友获得外,最直接的途径就是支付宝的咻一咻了。那么咻一咻具体有哪些实现方式呢?下面我们将一一介
- 在分布式系统架构中,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们
- 一般振动时间的配置在如下文件:frameworks/base/core/res/res/values/config.xml &nb
- 需求说明实际操作过程中,从D盘根目录下的ak.txt读取文件写入D盘根目录下的hello.txt文件内实现思路写两个方法,一个用于读取目标文
- 背景后台系统需要接入 企业微信登入,满足企业员工快速登入系统流程图简单代码说明自定义一套 springsecurity 认证逻辑主要就是 根
- 业务场景近年来B2C、O2O等商业概念的提出和移动端的发展,使得分布式系统流行了起来。分布式系统相对于单系统,解决了流量大、系统高可用和高容
- 1,如今NestedScrolling运用到很多地方了,要想好看一点的滑动变换,基本上就是使用这个来完成的,让我们来简单的了解一下。2,Ne
- 我们都知道且经常用到 unsigned 关键字,但有没有想过,与此对应的 signed 关键字有啥用?int i = 0;signed in
- 一、前言在mybatis官网中,有插件一说 mybatis plugins 如果同时有多个插件,那么他们的执行顺序是怎样的?二、准备工作、代
- 这篇文章主要介绍了Java继承方法重写实现原理及解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友
- ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,它就是一个容器,用于存放线程的局部变量,我认为
- 概述java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的