Silky微服务框架在线文档Silky微服务框架在线文档
首页
文档
配置
源码解析
博文
github
gitee
首页
文档
配置
源码解析
博文
github
gitee
  • 启动时

    • 主机的构建
    • 服务引擎
    • 模块
    • 服务与服务条目的解析
    • Silky服务主机
    • 依赖注入约定
    • RPC 服务代理
  • 运行时

    • 终结点与路由
    • 执行器与调度
    • 本地执行器与服务端过滤器
    • 远程执行器与 RPC 调用
    • RPC 服务端消息处理
    • 服务治理
    • 缓存拦截器
    • 分布式事务(TCC)
    • HTTP 网关请求管道
    • 过滤器执行管道
    • Polly 弹性策略管道
    • 端点健康监控

概述

silky 框架的底层 IoC 容器是 Autofac,通过将 AutofacServiceProviderFactory 注入到 .NET 主机中,替换默认的 IServiceCollection 容器,从而获得更强大的依赖注入能力。

除了直接使用 IServiceCollection.AddXxx() 或在 Autofac ContainerBuilder 中显式注册服务外,silky 还提供了一套约定式依赖注入机制:只要实现特定的标记接口,即可在框架启动时自动完成扫描和注册,无需任何手动注册代码。


约定注入接口

silky 提供三个标记接口,对应 Autofac 的三种生命周期:

接口对应 Autofac 生命周期说明
ITransientDependencyInstancePerDependency瞬时:每次解析都创建新实例
IScopedDependencyInstancePerLifetimeScope作用域:同一 Scope 内复用同一实例
ISingletonDependencySingleInstance单例:整个应用生命周期唯一实例

使用方式

// 瞬时:每次注入都是新实例
public class OrderService : IOrderService, ITransientDependency
{
}

// 作用域:在同一请求(Scope)内复用同一实例
public class CurrentUserContext : ICurrentUserContext, IScopedDependency
{
}

// 单例:整个应用共享同一实例
public class LocalServiceEntryManager : IServiceEntryManager, ISingletonDependency
{
}

框架在 DefaultDependencyRegistrar.Register() 中扫描所有已加载程序集,自动发现并注册这些类:

public class DefaultDependencyRegistrar : IDependencyRegistrar
{
    public void Register(ContainerBuilder builder, ITypeFinder typeFinder)
    {
        var refAssemblies = typeFinder.GetAssemblies();
        foreach (var assembly in refAssemblies)
        {
            // 单例注册
            builder.RegisterAssemblyTypes(assembly)
                .Where(t => typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(t)
                         && !t.GetCustomAttributes().OfType<InjectNamedAttribute>().Any())
                .PropertiesAutowired()
                .AsImplementedInterfaces()
                .AsSelf()
                .SingleInstance();

            // 瞬时注册
            builder.RegisterAssemblyTypes(assembly)
                .Where(t => typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(t)
                         && !t.GetCustomAttributes().OfType<InjectNamedAttribute>().Any())
                .PropertiesAutowired()
                .AsImplementedInterfaces()
                .AsSelf()
                .InstancePerDependency();

            // 作用域注册
            builder.RegisterAssemblyTypes(assembly)
                .Where(t => typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(t)
                         && !t.GetCustomAttributes().OfType<InjectNamedAttribute>().Any())
                .PropertiesAutowired()
                .AsImplementedInterfaces()
                .AsSelf()
                .InstancePerLifetimeScope();
        }
    }
}

注意两个关键点:

  • 所有约定注入的类都启用了 PropertiesAutowired(),即属性注入也受 Autofac 管理
  • 带有 [InjectNamed] 特性的类会被跳过,由 NamedServiceDependencyRegistrar 单独处理

属性注入(PropertiesAutowired)

通过约定接口注册的类,其公共属性会被 Autofac 自动注入(属性注入),无需在构造函数中声明依赖:

public class DefaultServerMessageReceivedHandler : ISingletonDependency
{
    // 属性注入:无需构造函数参数
    public ILogger<DefaultServerMessageReceivedHandler> Logger { get; set; }

    // 构造函数注入依然可用,两者可以混用
    public DefaultServerMessageReceivedHandler(IServiceEntryLocator locator)
    {
        _locator = locator;
    }
}

提示

silky 框架内部大量使用属性注入来注入 ILogger<T>,这样可以避免每个类都在构造函数中声明日志依赖。


命名注入(Named Service)

当同一接口有多个实现类,且需要通过名称区分时,使用 [InjectNamed] 特性:

[InjectNamed("Rpc")]
public class RpcParameterResolver : IParameterResolver, ITransientDependency
{
}

[InjectNamed("Dict")]
public class DictParameterResolver : IParameterResolver, ITransientDependency
{
}

[InjectNamed("Http")]
public class HttpParameterResolver : IParameterResolver, ITransientDependency
{
}

注册后,通过 Autofac 的命名解析获取特定实现:

// 根据消息的 ParameterType 名称动态解析对应的参数解析器
var parameterResolver = EngineContext.Current
    .ResolveNamed<IParameterResolver>(message.ParameterType.ToString());

NamedServiceDependencyRegistrar 负责扫描所有带 [InjectNamed] 特性的类,并按名称注册到 Autofac 容器:

// 伪代码:按名称注册
builder.RegisterType<RpcParameterResolver>()
    .Named<IParameterResolver>("Rpc")
    .InstancePerDependency();

模块中显式注册(RegisterServices)

除约定注入外,每个 SilkyModule 可以在 RegisterServices(ContainerBuilder builder) 方法中进行显式注册,适合需要精细控制生命周期或注册方式的场景:

public class RpcModule : SilkyModule
{
    protected override void RegisterServices(ContainerBuilder builder)
    {
        // 精细控制:按实现类注册,指定名称,或使用工厂方法
        builder.RegisterType<DefaultExecutor>()
               .As<IExecutor>()
               .SingleInstance();
    }
}

通过 IConfigureService 注册

实现 IConfigureService 接口的类,在 SilkyEngine.ConfigureServices() 阶段会被通过反射自动发现并执行,可以使用 IServiceCollection 进行服务注册:

public class RpcConfigureService : IConfigureService
{
    public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddHttpContextAccessor();
        services.AddOptions<RpcOptions>()
            .Bind(configuration.GetSection(RpcOptions.Rpc));
    }
}

优先级与注册顺序

silky 的依赖注入分为以下几个阶段,按此顺序执行:

(1) IConfigureService 实现类(通过反射发现,使用 IServiceCollection 注册)
        ↓
(2) SilkyModule.ConfigureServices()(各模块,使用 IServiceCollection 注册)
        ↓
(3) SilkyModule.RegisterServices()(各模块,使用 ContainerBuilder 注册)
        ↓
(4) DefaultDependencyRegistrar(约定扫描,使用 ContainerBuilder 自动注册)
        ↓
(5) NamedServiceDependencyRegistrar(命名服务扫描,使用 ContainerBuilder 注册)

Warning

Autofac 中后注册的覆盖先注册的(默认行为)。因此,约定扫描(步骤 4/5)的注册在模块显式注册(步骤 3)之后执行,这意味着如果模块和约定类都注册了同一接口,最终生效的是约定扫描的实现。若要保证模块注册优先,需使用 PreserveExistingDefaults()。


框架上下文(EngineContext)

在无法通过构造函数或属性注入获取服务的场景(如静态类、工厂方法内部),可以通过 EngineContext.Current 手动解析:

// 解析已注册的服务
var executor = EngineContext.Current.Resolve<IExecutor>();

// 按名称解析
var resolver = EngineContext.Current.ResolveNamed<IParameterResolver>("Rpc");

// 判断某服务是否已注册
var isRegistered = EngineContext.Current.IsRegistered<IFallbackProvider>();

EngineContext.Current 是 IEngine(SilkyEngine)的单例引用,其 ServiceProvider 属性在 InitSilkyHostedService 启动后被初始化,此后可在整个应用生命周期中安全使用。


选择合适的注入方式

场景推荐方式
框架内核服务(Silky 自身组件)ISingletonDependency 约定注入
每次请求独立的业务服务IScopedDependency 约定注入
无状态工具类、帮助器ITransientDependency 约定注入
同接口多实现,按名称区分[InjectNamed] + 约定注入
需要精细控制注册参数模块 RegisterServices() 显式注册
第三方库、ASP.NET Core 中间件IConfigureService 或模块 ConfigureServices()
编辑当前页
Prev
Silky服务主机
Next
RPC 服务代理