依赖注入

被子太轻,压不住想你的心。 --zhu
依赖注入概念
生活中的“控制反转”:
自己发电和用电网的电。
依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。
依赖注入简化模块的组装过程,降低模块之间的耦合度。

代码控制反转的目的
“怎么创建XX对象”->“我要XX对象”
两种实现方式:
(1)服务定位器(ServiceLocator);

IDbConnection conn=ServiceLocator.GetService<IDbConnection>();

(2)依赖注入(Dependency Injection,DI);

class Demo
{
  public IDbConnection Conn{get;set;}
  public void InsertDB()
  {
    IDbConnection  cmd=Conn.CreateCommand();
  }
}

DI概念
服务(Service):对象;
注册服务;
服务容器:负责管理注册的服务;
查询服务:创建对象及关联对象;
对象生命周期:Transient(瞬态);Scoped(范围);Singleton(单例);

.NET中使用DI
1.Install-Package Microsoft.Extensions.DependencyInjection
2.using Microsoft.Extensions.DependencyInjection
3.ServiceCollection用来构造容器对象IServiceProvider()创建的ServiceProvider,可以用来获取BuildServiceProvider()之前ServiceCollection中的对象。

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceCollection services = new ServiceCollection();
            services.AddTransient<TestServiceImpl>();
            //services.AddSingleton<TestServiceImpl>();
            //services.AddScoped<TestServiceImpl>();

            using (ServiceProvider sp = services.BuildServiceProvider())//服务定位器 ServiceProvider
            {
                TestServiceImpl t = sp.GetService<TestServiceImpl>();
                t.Name = "Lily";
                t.SayHi();

                TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
                t1.Name = "Tom";
                t1.SayHi();
                Console.WriteLine(object.ReferenceEquals(t, t1));
                t.SayHi();


                TestServiceImpl tt1;
                using (IServiceScope scope = sp.CreateScope())
                {
                    TestServiceImpl ts= scope.ServiceProvider.GetService<TestServiceImpl>();
                    t.Name = "Lily";
                    t.SayHi();
                    tt1 = ts;
                }

                using (IServiceScope scope = sp.CreateScope())
                {
                    TestServiceImpl ts = scope.ServiceProvider.GetService<TestServiceImpl>();
                    t.Name = "Lily";
                    t.SayHi();
                    Console.WriteLine(object.ReferenceEquals(tt1, ts));
                }
            }

   
                Console.Read();
        }
    }

    internal class TestServiceImpl : ITestService
    {
        public string Name { get ; set; }

        public void SayHi()
        {
            Console.WriteLine($"Hi,I'm {Name}");
        }
    }
    public interface ITestService
    {
        public string Name { get; set; }
        public void SayHi();
    }
}

结果:

Hi,I'm Lily
Hi,I'm Tom
False
Hi,I'm Lily
Hi,I'm Lily
Hi,I'm Lily
False

生命周期
1.给类构造函数中打印,看看不同生命周期的对象创建,使用serviceProvider.CreateScope()创建Scope。
2.如果一个类实现了IDisposable接口,则离开作用域之后,容器会自动调用对象的Dispose方法。
3.不要在长生命周期的对象中引用比它短的生命周期的对象。在.NET Core中,会默认抛异常。
4.生命周期的选择:如果类无状态,建议为Singleton;如果类有状态,且有Scpoe控制,建议为Scoped,因为通常这种Scope控制下的代码都是运行在同一个线程中的,没有并发修改的问题;在使用Transient的时候要严谨。
5..NET注册服务的重载方法很多,多看官方文档。

IServiceProvider的服务定位器方法:
1.T GetService() 如果获取不到对象,则返回null。(多个时,返回最后一个注册的)
object GetService(Type serviceType)
2.T GetRequireService() 如果获取不到对象,则抛异常。
object GetRequireService(Type serviceType)
3.IEnumerable GetServices()适用于可能有很多满足条件的服务。(多个s)
IEnumerable

posted on 2024-07-07 23:12  小脑虎爱学习  阅读(1)  评论(0编辑  收藏  举报