C#动态建立接口的实现实例对象

2021年11月25日 阅读数:4
这篇文章主要向大家介绍C#动态建立接口的实现实例对象,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

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

1.如何获取接口interface的全部实现实例对象?github

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

准备工做

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

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

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

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

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();

  运行结果如图所示get

   若是咱们想要一次性将全部实现了IAnimal接口对象Cry方法的实例所有执行一遍,只能一个对象一个对象的初始化,而后调用cry方法。这样太麻烦,咱们能够经过动态建立对象并执行对象的方法来实现这个效果。   string

下面,咱们将开始动态建立全部实现。第一步,咱们须要先获取到全部实现了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

  码云