Skip to content

Latest commit

 

History

History
176 lines (156 loc) · 6.83 KB

README.md

File metadata and controls

176 lines (156 loc) · 6.83 KB

NAutowired

NuGet NuGet GitHub issues GitHub repo size in bytes GitHub top language

ASP.NET Core 通过属性注入依赖

理念与定位

  • 我们不做容器,我们只是NET Core Container的搬运工(在默认容器的基础上增加了一些功能)。
  • 不要在构造函数中使用NAutowired
  • 由于我们与那些妖艳的第三方IoC Container有些不同,我们没有替换NetCore默认的Container,这意味着您依然可以在Startup里使用IServiceCollection将服务加入到Container并使用NAutowired还原这些依赖。
  • 虽然有人觉得Spring风格的DI有点反模式显式依赖),但是写起来爽。

如何使用

  • nuget包管理器中引入NAutowiredNAutowired.Core
  • NAutowired包应该只在Web或Console项目中被引用,NAutowired.Core包则在需要添加特性的项目中被引用。

ASP.NET Core 3.0

默认情况下,ASP.NET Core生成Controller时从容器中解析Controller构造函数中的依赖,但是不从容器中还原控制器,这导致:

  • Controller的生命周期由框架处理,而不是请求的生命周期
  • Controller构造函数中参数的生命周期由请求生命周期处理
  • Controller中通过属性注入将不起作用

您必须使用AddControllersAsServices方法,将Controller注册为Service,以便Controller在还原时使用属性注入

Startup.cs中使用AddControllersAsServices并替换IControllerActivator实现为NAutowiredControllerActivator

public void ConfigureServices(IServiceCollection services) {
    //register controllers as services
    services.AddControllers().AddControllersAsServices();
    //replace `IControllerActivator` implement.
    services.Replace(ServiceDescriptor.Transient<IControllerActivator, NAutowiredControllerActivator>());
}

使用Autowired

  public class Startup {
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services) {
      //将FooService加到容器
      services.AddScoped<FooService>();
    }
  }
  [Route("api/[controller]")]
  [ApiController]
  public class FooController : ControllerBase {

    //使用Autowired Attribute注入实例
    [Autowired]
    private readonly FooService fooService;

    [HttpGet]
    public ActionResult<string> Get() {
      return fooService == null ? "failure" : "success";
    }
  }

Filter中使用NAutowired

  public class Startup {
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services) {
      //将Filter加到容器
      services.AddScoped<AuthorizationFilter>();
    }
  }
  //使用 ServiceFilterAttribute
  [NAutowired.Attributes.ServiceFilter(typeof(AuthorizationFilter))]
  public class FooController : ControllerBase {

  }
  public class AuthorizationFilter : IAuthorizationFilter {
    [Autowired]
    private readonly FooService fooService;

    public void OnAuthorization(AuthorizationFilterContext context) {
      System.Console.WriteLine($"{fooService.ToString()} in filter");
      return;
    }
  }

NET Core 3.0 Console

新建Srartup.cs文件,并且继承自NAutowired.Core.Startup

public class Startup : NAutowired.Core.Startup
{
    [Autowired]
    private readonly FooService fooService;

    //程序启动时将会执行此方法
    public override void Run(string[] args)
    {
        System.Console.WriteLine(fooService.Foo());
        System.Console.ReadLine();
    }
}

Program.cs

class Program
{
    static void Main(string[] args)
    {
        ConsoleHost.CreateDefaultBuilder(new List<string> {  "assemblyName" }, args).Build().Run<Startup>();
        //你也可以让NAutowired使用你传递的IServiceCollection
        /*
        ConsoleHost.CreateDefaultBuilder(() => {
          var serviceDescriptors = new ServiceCollection();
          serviceDescriptors.AddTransient<FooService>();
          return serviceDescriptors;
        }, new List<string> { "NAutowiredConsoleSample" }, args).Build().Run<Startup>();
        */
    }
}

单元测试

进阶

您可以通过[Autowired(Type)]方式注入特定的类型

  [Route("api/[controller]")]
  [ApiController]
  public class FooController : ControllerBase {

    //注入特定的实例
    [Autowired(typeof(FooService))]
    private readonly IService service;

    [HttpGet]
    public ActionResult<string> Get() {
      return service == null ? "failure" : "success";
    }
  }

NAutowired提供了AutoRegisterDependency方法进行自动容器注入.这种方式让您无需在Startup.cs中一个个的将类型加入到容器

  public class Startup {
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services) {
      //使用自动注入
      services.AutoRegisterDependency(new List<string> { "NAutowiredSample" });
    }
  }

使用[Service] [Repository] [Component] [ServiceFilter]特性标记类,这些类将在AutoRegisterDependency执行时被加入到容器

  //默认Lifetime值为Scoped
  [Service]
  //Lifetime可供选择依赖注入的生命周期
  //[Service(Lifetime.Singleton)]
  public class FooService {
  }

  [Service(implementInterface: typeof(IService))]
  //注入特定的实现类到容器。这将执行services.AddScoped(typeof(IService), typeof(FooService));
  public class FooService: IService {
  }

NAutowired会自动扫描AutoRegisterDependency(assemblyNames)方法配置的程序集下的所有类,并将具有[Service] [Repository] [Component] [ServiceFilter]特性的类注入到容器。