C # dynamically creates the implementation instance object of the interface

Keywords: ASP.NET C# interface reflection

This article briefly introduces how to dynamically create the implementation instance object of the interface, including two knowledge points:

1. How to obtain all implementation instance objects of the interface?

2. How to judge whether the constructor of an instance object has parameters?

preparation

First, create an interface object named IAnimal and define a Cry method.

namespace DynamicCreate
{
    /// <summary>
    ///Animal
    /// </summary>
    public interface IAnimal
    {
        /// <summary>
        ///Call
        /// </summary>
        public void Cry();
    }
}

Then, we create a Dog and Cat object respectively, and implement the Cry method respectively.

The constructor of Dog contains a parameter named name.

namespace DynamicCreate
{
    /// <summary>
    ///Dog
    /// </summary>
    public class Dog : IAnimal
    {
        /// <summary>
        ///Name
        /// </summary>
        private string _name { get; }

        /// <summary>
        ///Parameterized constructor
        /// </summary>
        ///< param name = "name" > dog name < / param >
        public Dog(string name)
        {
            _name = name;
        }

        /// <summary>
        ///Dog barking
        /// </summary>
        public void Cry()
        {
            Console.WriteLine($"{_name}Woof, woof");
        }
    }
}

Cat's constructor is a parameterless constructor.

namespace DynamicCreate
{
    /// <summary>
    ///Cat
    /// </summary>
    public class Cat : IAnimal
    {
        /// <summary>
        ///Parameterless constructor
        /// </summary>
        public Cat()
        {

        }

        /// <summary>
        ///Cat barking
        /// </summary>
        public void Cry()
        {
            Console.WriteLine("cat ");
        }
    }
}

The general calling methods are as follows.

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

The operation results are shown in the figure

  If we want to execute all instances of the IAnimal interface object Cry method at once, we can only initialize one object and one object, and then call the cry method. This is too troublesome. We can achieve this effect by dynamically creating and executing objects.     

Next, we'll start creating all the implementations dynamically. In the first step, we need to get all the instance objects that implement IAnimal.

1. How to obtain all implementation instance objects of the interface?

Get the list of assembly objects in the current project through reflection, and get the list of objects that inherit or implement the IAnimal interface according to the type of assembly objects.

//Gets an instance object that implements the interface IAnimal
var types = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IAnimal))))
                        .ToList(); 

Let's print out the results and have a look

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

  

   Now we have all the instance objects that implement the IAnimal interface. It makes sense that we can create these objects dynamically with Activator. We can use the following code to realize batch dynamic creation of objects.

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

However, an error message appears: Dog does not contain a parameterless constructor.

  Therefore, when creating, you need to pass in the constructor parameter name of Dog, as shown below.

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

However, once again, the constructor for Cat does not exist.

  This is because Cat does not contain a constructor with parameters, as shown, the Cat object cannot be initialized. Therefore, we need to determine whether the object is a parameterized constructor or a nonparametric constructor.

2. How to judge whether the constructor of an instance object has parameters?

We can get the constructor set of the object through the GetConstructors method, and get the parameter set of the constructor through the GetParameters method. Judge whether the parameter set of the constructor is empty, and then judge whether the constructor of the object is a parameterized or nonparametric constructor.

foreach (Type v in types)
{
    if (v.GetConstructors().Any(x => x.GetParameters().Any()))
    {
        Console.WriteLine($"{v.Name}=>Parameterized constructor");
    }
    else
    {
        Console.WriteLine($"{v.Name}=>non-parameter constructor ");
    }
}

  

   Now we can happily create the object and call the object's methods.

foreach (Type t in types)
{
    IAnimal animal;
    if (t.GetConstructors().Any(x => x.GetParameters().Any()))
    {
        //Parameterized constructor
        //Dynamically create a parameterized constructor of IAnimal to implement the instance object Dog
        animal = (IAnimal)Activator.CreateInstance(t, new object[] { "Ah Huang" })!;
    }
    else
    {
        //non-parameter constructor 
        //Dynamically create a parameterless constructor of IAnimal to implement the instance object
        animal = (IAnimal)Activator.CreateInstance(t, new object[] { })!;
    }
    animal.Cry();
}

  

  

  Finally, attach the complete code, please don't spray me.

  GitHub

  Code cloud

 

Posted by lingo5 on Wed, 24 Nov 2021 08:05:42 -0800