(精华)2020年12月24日 .NET Core 自带依赖注入的实现原理

以控制台程序为例引入以下来个程序集

Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.DependencyInjection.Abstractions

1.创建服务和接口获取服务的基本使用

public static class Sample01
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public class Account: IAccount{}
    public class Message: IMessage{}
    public class Tool: ITool{}

    public static void Run()
    {
        var provider = new ServiceCollection()
            .AddTransient<IAccount, Account>()
            .AddScoped<IMessage, Message>()
            .AddSingleton<ITool, Tool>()
            .BuildServiceProvider();

        Debug.Assert(provider.GetService<IAccount>() is Account);
        Debug.Assert(provider.GetService<IMessage>() is Message);
        Debug.Assert(provider.GetService<ITool>() is Tool);
    }
}

2.创建服务和父类获取服务的基本使用

public static class Sample02
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public class Base
    {
        public Base()
        {
            Console.WriteLine($"{GetType().Name} 已创建");
        }
    }

    public class Account:Base, IAccount{}
    public class Message:Base, IMessage{}
    public class Tool:Base, ITool{}

    public static void Run()
    {
        var services = new ServiceCollection()
            .AddTransient<Base, Account>()
            .AddTransient<Base, Message>()
            .AddTransient<Base, Tool>()
            .BuildServiceProvider()
            .GetServices<Base>().ToList();

        Debug.Assert(services.OfType<Account>().Any());
        Debug.Assert(services.OfType<Message>().Any());
        Debug.Assert(services.OfType<Tool>().Any());
    }
}

3.生命周期和作用域

public static class Sample03
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public class Base
    {
        public Base()
        {
            Console.WriteLine($"Created:{GetType().Name}");
        }

    }

    public class Account: Base, IAccount{}
    public class Message:Base, IMessage{}
    public class Tool:Base, ITool{}

    public static void Run()
    {
        var root = new ServiceCollection()
            .AddTransient<IAccount, Account>()
            .AddScoped<IMessage, Message>()
            .AddSingleton<ITool, Tool>()
            .BuildServiceProvider();

        var child1 = root.CreateScope().ServiceProvider;
        var child2 = root.CreateScope().ServiceProvider;

        GetService<IAccount>(child1);
        GetService<IMessage>(child1);
        GetService<ITool>(child1);
        Console.WriteLine();
        GetService<IAccount>(child2);
        GetService<IMessage>(child2);
        GetService<ITool>(child2);
    }

    public static void GetService<T>(IServiceProvider provider)
    {
        provider.GetService<T>();
        provider.GetService<T>();
    }
}

4.释放容器

public static class Sample04
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public class Base : IDisposable
    {
        public Base()
        {
            Console.WriteLine($"Created:{GetType().Name}");
        }


        public void Dispose()
        {
            Console.WriteLine($"Disposed: {GetType().Name}");
        }
    }

    public class Account: Base, IAccount{}
    public class Message:Base, IMessage{}
    public class Tool:Base, ITool{}

    public static void Run()
    {
    	//释放根容器ITool
        using (var root = new ServiceCollection()
            .AddTransient<IAccount, Account>()
            .AddScoped<IMessage, Message>()
            .AddSingleton<ITool, Tool>()
            .BuildServiceProvider())
        {
        	//释放子容器IAccount,IMessage
            using (var scope = root.CreateScope())
            {
                var child = scope.ServiceProvider;
                child.GetService<IAccount>();
                child.GetService<IMessage>();
                child.GetService<ITool>();
                Console.WriteLine("释放子容器");
            }
            Console.WriteLine("释放根容器");
        }
    }
}

5.类构造函数重载注入的选择

public static class Sample05
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public interface ITest{ }

    public class Account: IAccount{}
    public class Message: IMessage{}
    public class Tool: ITool{}
    public class Test: ITest
    {
        // 如果某个构造函数的参数类型集合,能够称为所有合法构造函数参数类型集合的超集
        // 那个这个构造函数就会被服务提供对象所选择。
        public Test(IAccount account)
        {
            Console.WriteLine($"Ctor:Test(IAccount)");
        }
        //选这个前面服务注入了两个
        public Test(IAccount account, IMessage message)
        {
            Console.WriteLine($"Ctor:Test(IAccount,IMessage)");
        }

        public Test(IAccount account, IMessage message, ITool tool)
        {
            Console.WriteLine($"Ctor:Test(IAccount,IMessage,ITool)");
        }
    }

    public static void Run()
    {
        var test = new ServiceCollection()
            .AddTransient<IAccount, Account>()
            .AddTransient<IMessage, Message>()
            .AddTransient<ITest, Test>()
            .BuildServiceProvider()
            .GetService<ITest>();
    }
}

5.类构造函数重载注入的选择

多安装以下两个包

Autofac
Autofac.Extensions.DependencyInjection

替换自带依赖注入容器

public static class Sample02
{
    public interface IAccount{ }
    public interface IMessage{ }
    public interface ITool{ }

    public interface ITest
    {
        public IMessage Message { get; set; }
    }


    public class Base
    {
        public Base()
        {
            Console.WriteLine($"Created:{GetType().Name}");
        }

    }

    public class Account:Base, IAccount{}
    public class Message:Base, IMessage{}

    public class Tool : Base, ITool { }

    public class Test: ITest
    {
        public IMessage Message { get; set; }

        public Test(IAccount account, ITool tool)
        {
            Console.WriteLine($"Ctor:Test(IAccount, ITool)");
        }
    }

    public static void Run()
    {
        var serviceCollection = new ServiceCollection()
            .AddTransient<ITool, Tool>();

        var containerBuilder = new ContainerBuilder();

        containerBuilder.Populate(serviceCollection);
        // 属性注入
        containerBuilder.RegisterType<Test>().As<ITest>().PropertiesAutowired();
        // 程序集注册
        containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            // 筛选基类为Base
            .Where(t => t.BaseType == typeof(Base))
            // 暴露第一个接口
            .As(t => t.GetInterfaces()[0])
            // 生命周期模式为Scope
            .InstancePerLifetimeScope();

        var container = containerBuilder.Build();
        IServiceProvider provider = new AutofacServiceProvider(container);
        
        Debug.Assert(provider.GetService<IAccount>() is Account);
        Debug.Assert(provider.GetService<IMessage>() is Message);
        Debug.Assert(provider.GetService<ITool>() is Tool);

        var test = provider.GetService<ITest>();
        Debug.Assert(test.Message is Message);
        Console.Read();
    }
}

使用

public static class Sample03
{
    public interface IAccount{ }
    public interface ITool{ }

    public interface IMessageService { }

    public class EmailMessageService : IMessageService
    {
        public IAccount Account { get; set; }
        public ITool Tool { get; set; }

        public EmailMessageService(IAccount account, ITool tool)
        {
            Account = account;
            Tool = tool;
        }

        public void Test()
        {
            Console.WriteLine(Account.GetHashCode());
            Console.WriteLine(Tool.GetHashCode());
        }
    }

    public class SmsMessageService : IMessageService
    {
        public IServiceProvider ServiceProvider { get; set; }

        public SmsMessageService(IServiceProvider serviceProvider)
        {
            ServiceProvider = serviceProvider;
        }

        public void Test()
        {
            Console.WriteLine(ServiceProvider.GetService<IAccount>().GetHashCode());
            Console.WriteLine(ServiceProvider.GetService<ITool>().GetHashCode());
        }
    }

}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页