.NET的依赖注入框架Microsoft.Extensions.DependencyInjection,支持注入未绑定的泛型类(Unbound generic type)

C#的关键字typeof可以用来获取未绑定的泛型类/接口(Unbound generic type)的Type类实例,未绑定的泛型类/接口(Unbound generic type)就是指没有指定类型参数的泛型类/接口,如下代码所示:

using System;

namespace NET5UnboundGenericDependencyInjectionDemos
{
    /// <summary>
    /// 泛型类Container<T>
    /// </summary>
    /// <typeparam name="T">泛型类型参数</typeparam>
    class Container<T>
    {

    }

    class Program
    {
        static void Main(string[] args)
        {
            Type unboundGenericType = typeof(Container<>);//通过typeof关键字,获取未绑定的泛型类Container<T>的Type类实例

            Console.WriteLine(unboundGenericType.ToString());

            Console.WriteLine("Press any key to end...");
            Console.ReadKey();
        }
    }
}

运行上面代码,结果如下:

可以看到Type类实例unboundGenericType输出的信息中,泛型类Container<T>的类型参数T,并没有被指定为具体的类型,所以是未绑定的泛型类。

未绑定的泛型类常常被用于依赖注入中,这样可以大大增加代码的复用性,而微软的依赖注入框架Microsoft.Extensions.DependencyInjection支持注入未绑定的泛型类。

首先我们创建一个.NET 5.0控制台项目,然后引入nuget包:Microsoft.Extensions.DependencyInjection

项目的代码如下所示:

using Microsoft.Extensions.DependencyInjection;
using System;

namespace NET5UnboundGenericDependencyInjectionDemos
{
    /// <summary>
    /// 泛型接口IContainer<T>
    /// </summary>
    /// <typeparam name="T">泛型类型参数,where T : new()约束保证类型T具有公共无参数构造函数</typeparam>
    interface IContainer<T> where T : new()
    {
        T Element
        {
            get;
        }

        /// <summary>
        /// 显示泛型类型参数T的Type类型
        /// </summary>
        void ShowElementType();
    }

    /// <summary>
    /// 泛型类Container<T>,实现接口IContainer<T>
    /// </summary>
    /// <typeparam name="T">泛型类型参数,where T : new()约束保证类型T具有公共无参数构造函数</typeparam>
    class Container<T> : IContainer<T> where T : new()
    {
        protected T element;

        public Container()
        {
            element = new T();
        }

        public T Element
        {
            get
            {
                return element;
            }
        }

        /// <summary>
        /// 显示泛型类型参数T的Type类型
        /// </summary>
        public void ShowElementType()
        {
            Console.WriteLine(element.GetType().ToString());
        }
    }

    /// <summary>
    /// 类People,作为泛型接口IContainer<T>和泛型类Container<T>的类型参数T
    /// </summary>
    class People
    {
        public void Speak()
        {
            Console.WriteLine("I'm a people!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IServiceCollection serviceDescriptors = new ServiceCollection();
            serviceDescriptors.AddTransient(typeof(IContainer<>), typeof(Container<>));//注册未绑定的泛型接口IContainer<T>和未绑定的泛型类Container<T>的依赖注入关系

            IContainer<People> container = null;//声明关闭的泛型接口IContainer<People>变量container,下面使用依赖注入来为其赋值

            using (ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider())
            {
                using (IServiceScope serviceScope = serviceProvider.CreateScope())
                {
                    container = serviceScope.ServiceProvider.GetService<IContainer<People>>();//使用依赖注入为泛型接口IContainer<People>变量container赋值,依赖注入框架Microsoft.Extensions.DependencyInjection会构造一个关闭的泛型类Container<People>实例,赋值给IContainer<People> container
                }
            }

            Console.WriteLine(container.GetType().ToString());//显示泛型接口IContainer<People>变量container的实际类型
            container.ShowElementType();//调用泛型接口IContainer<People>的ShowElementType方法
            container.Element.Speak();//调用泛型接口IContainer<People>的类型参数People的Speak方法

            Console.WriteLine("Press any key to end...");
            Console.ReadKey();
        }
    }
}

运行上面代码,结果如下:

我们可以看到,使用依赖注入框架Microsoft.Extensions.DependencyInjection,我们可以为关闭的泛型接口(Closed generic type)IContainer<People>,来注入关闭的泛型类(Closed generic type)Container<People>,关闭的泛型类/接口(Closed generic type)就是指指定了具体类型参数的泛型类/接口,上面代码中泛型的类型参数就是People类。

注意上面代码中,我们在注册依赖注入关系的时候(AddTransient),是注册的未绑定的泛型接口IContainer<T>和未绑定的泛型类Container<T>的依赖注入关系,但是依赖注入框架Microsoft.Extensions.DependencyInjection,还是可以为关闭的泛型接口IContainer<People>,获得关闭的泛型类Container<People>。

原文地址:https://www.cnblogs.com/OpenCoder/p/14707127.html