• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

什么情况下需要引入第三方容器组件?

实际上,默认的容器组件在大多数情况下已经足够我们使用了,但是当我们需要一些非常特殊的场景时,比如:

基于名称的注入:当一个服务通过它的名字从它的不同实现中被区分出来时。

属性注入:我们的注入方法有FromService和构造函数参与,但是在开源社区中,我们有很多这样的属性注入方法,也就是说我们可以直接将服务注册到某个类的属性中,而不需要定义构造函数。

子容器: It可以理解为前面提到的范围,但实际上,我们也可以使用第三方框架来实现一些特殊的子容器。

基于动态代理的AOP:当我们需要将我们额外的行为注入到服务中时,我们可以使用动态代理的能力。

的核心扩展点。NET Core的依赖注入框架是:iServiceProviderFactoryPubic接口iServiceProviderFactoryContainer Builder

第三方依赖注入容器都是用这个类作为扩展点,把自己注入到我们整个框架中。也就是说,我们在使用这些依赖注入框架的时候,不需要注意说:谁的特性,谁的接口像,我们只需要使用官方核心的定义,不需要直接依赖这些框架;

公共接口IMyService{

void show code();

}

公共类MyService: IMyService{

public void ShowCode(){

控制台。WriteLine($'MyService。show code : { get hashcode()} ');

}

}

公共类MyServiceV2: IMyService {

public MyNameService NameService { get;设置;}

public void ShowCode(){

console . writeline($ ' my service v2 . showcode 3360 { get hashcode()},nameservice是否为空:{ name service==null } ');

}

}

公共类MyNameService{}

介绍Autofac软件包:

Autofac。扩展.依赖注入

Autofac。临时演员。动态代理

添加到导入文件:

image

的作用。useServiceProviderFactory(newAutoFacServiceProviderFactory()):注册第三方容器的条目。

在Startup.cs中添加ConfigureContainer方法3360

public void configure container(container builder生成器){

//一般的写法:先注册具体的实现,然后告诉它我们要标记哪种服务类型,和前面用自注入的写法相反。

建筑商。RegisterTypeMyService()。asimy service();

//名称注册:当我们需要多次注册一个服务,并使用不同的名称进行区分时,可以使用这种方法。

建筑商。RegisterTypeMyServiceV2()。namedimy service(' service 2 ');

}

如何使用上面代码中的命名注册?在Starup.cs中:

public ILifetimeScope autoaccontainer { get;私有集;}//这里是向容器注册。

public void Configure(IApplicationBuilder应用程序,IWebHostEnvironment环境){

这个。AutofacContainer=app。application services . GetAutofacRoot();

//自动

fac容器获取实例的方式是一组Resolve的方法, ResolveNamed 和 ResolveKey 作用相同,用法不同而已; var service = this.AutofacContainer.ResolveNamed<IMyService>("service2"); service.ShowCode(); // 这里输出的是 MyServiceV2 var servicenamed = this.AutofacContainer.Resolve<IMyService>(); servicenamed.ShowCode(); // 这里输出的是 MyService ... }

运行后输出:
image

注意:Autofac容器获取实例的方式是一组Resolve的方法:
image

属性注入

只需要在后面加入 .PropertiesAutowired() 即可:

public void ConfigureContainer(ContainerBuilder builder)
{
    //// 一般的写法:先注册具体的实现,然后再告诉它我们想把它标记哪个服务的类型
    //builder.RegisterType<MyService>().As<IMyService>();
    //// 命名注册:当我们需要把一个服务注册多次,并且用不同的命名来作为区分的时候,我们可以用这种方式
    //builder.RegisterType<MyServiceV2>().Named<IMyService>("service2");
    builder.RegisterType<MyServiceV2>().As<IMyService>().PropertiesAutowired();
}
public ILifetimeScope AutofacContainer{get; private set;}   // 这里是把根容器注册进来
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){
    this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
    // Autofac容器获取实例的方式是一组Resolve的方法
    //var service = this.AutofacContainer.ResolveNamed<IMyService>("service2");
    //service.ShowCode();       // 这里输出的是 MyServiceV2
    var servicenamed = this.AutofacContainer.Resolve<IMyService>();
    servicenamed.ShowCode();       // 这里输出的是 MyService
    ...
}

image
NameService为空,说明 NameService 属性没有注入进来
我们需要将 MyNameService 也注入进容器中:

public void ConfigureContainer(ContainerBuilder builder)
{
    //// 一般的写法:先注册具体的实现,然后再告诉它我们想把它标记哪个服务的类型
    //builder.RegisterType<MyService>().As<IMyService>();
    //// 命名注册:当我们需要把一个服务注册多次,并且用不同的命名来作为区分的时候,我们可以用这种方式
    //builder.RegisterType<MyServiceV2>().Named<IMyService>("service2");
    builder.RegisterType<MyServiceV2>().As<IMyService>().PropertiesAutowired();
    builder.RegisterType<MyNameService>();
}

image
发现 MyNameService 已经不为空了,说明 NameService 已经有实例了,属性注入已经成功了

AOP

我们在不期望改变原有类的情况下,在方法执行时嵌入一些逻辑,让我们可以在方法执行的切面上任意的插入我们的逻辑

public class MyInterceptor: IInterceptor    // 类必须要继承至 IInterceptor,并且要实现 Intercept方法
{
    public void Intercept(IInvocation invocation)
    {
        System.Console.WriteLine($"Intercept before,Method:{invocation.Method.Name}");
        invocation.Proceed();
        System.Console.WriteLine($"Intercept after,Method:{invocation.Method.Name}");
    }
}
public void ConfigureContainer(ContainerBuilder builder)
{
    // 首先我们需要把我们的拦截器MyInterceptor注册到容器里面去
    builder.RegisterType<MyInterceptor>();
    // 然后我们把MyServiceV2注册进去,并且允许它属性注册,开启拦截器需要我们使用InterceptedBy这个方法,并且把我们的类型注册进去,最后还要执行一个开关让我们允许接口拦截器
	// 拦截器分两种类型,一种是接口类型的接口拦截器(常用)和类拦截器,当我们的服务的类型是接口的时候就需要用接口拦截器类型;而如果我们没有基于接口设计我们的类,而是去实现了类的话,我们就需要用类拦截器,类拦截器需要我们把方法设计为虚方法,这样子允许继承类重载的情况下,才可以拦截到我们的具体方法
    builder.RegisterType<MyServiceV2>().As<IMyService>().PropertiesAutowired().InterceptedBy(typeof(MyInterceptor)).EnableInterfaceInterceptors();
}
public ILifetimeScope AutofacContainer{get; private set;}   // 这里是把根容器注册进来
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){
    this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
    var servicenamed = this.AutofacContainer.Resolve<IMyService>();
    servicenamed.ShowCode();       // 这里输出的是 MyService
    ...
}

image

子容器

我们可以创建Scope来作为子容器;
下面代码中,我们实际上是可以给子容器进行命名,Autofac具备给子容器进行命名的特性;

#region 子容器
这里我们可以把一个服务注入到子容器中,并且是特定的命名的子容器,那就意味着我们在其他的子容器里面是获取不到这个对象的;
builder.RegisterType<MyNameService>().InstancePerMatchingLifetimeScope("myscope");
#endregion
public ILifetimeScope AutofacContainer { get; private set; }   // 这里是把跟容器注册进来
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
    #region 子容器
    using(var myscope = AutofacContainer.BeginLifetimeScope("myscope"))
    {
        var service0 = myscope.Resolve<MyNameService>();
        using (var scope = myscope.BeginLifetimeScope())
        {
            var service1 = scope.Resolve<MyNameService>();
            var service2 = scope.Resolve<MyNameService>();
            Console.WriteLine($"service1=service2:{service1 == service2}");
            Console.WriteLine($"service1=service0:{service1 == service0}");
        }
    }
    #endregion
    ...
}

image

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now