本文简单介绍如何动态创建接口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#实现动态创建接口并调用的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。