跳到主要内容

IGeekFan.FreeKit.Infrastructure

核心基础设施项目(src/BuildingBlocks/IGeekFan.FreeKit.Infrastructure,目标框架 net10.0),提供贯穿各层的基类与横切能力:Controller 基类、应用/领域服务基类、认证授权、缓存、异常体系、加解密、中间件、过滤器、DTO 与扩展方法。它是 BuildingBlocks 中最底层、被其它构建块与所有业务模块共享的"全家桶"约定层。

:::info 依赖 本项目无任何本地 ProjectReference,全部通过 NuGet 引用:

  • IGeekFan.FreeKit.Extras / IGeekFan.FreeKit.Modularity / IGeekFan.FreeKit.Email / IGeekFan.Localization.FreeSql(版本 0.0.554
  • FreeSql + FreeSql.Repository 及扩展、FreeRedis + FreeRedis.DistributedCache
  • DotNetCore.CAP(MySQL / RabbitMQ / InMemory / Dashboard)、MapsterSerilog.*AspNetCoreRateLimitOwl.reCAPTCHAArdalis.GuardClausesIP2Region.Net / IPTools.ChinaHtmlAgilityPackSystem.IO.Hashing 等 :::

模块与命名空间

文件夹命名空间职责
Application/...Infrastructure.ApplicationController 基类、ApplicationServiceCrudAppService
DDD/...Infrastructure.DDDDomainServiceIDomainEventDispatcher
Caches/...Infrastructure.CachesICacheServiceCacheableAttribute、Provider
Exceptions/...Infrastructure.ExceptionsBusinessExceptionGuardExtensions
Contracts/...Infrastructure.ContractsResponseCodeClaimsConstsAuthenticationConst
Authentication/...Infrastructure.AuthenticationCookieJwtBearerHandlerAuthMode
Authorization/...Infrastructure.AuthorizationKitAuthorizeAttributeIPermissionStore、策略
Security/...Infrastructure.SecurityCurrentUserExtensionsCryptoUtil
DTO/...Infrastructure.DTOApiResponsePageQueryEnumDtoJwtSettings
Utils/ / Tools...Infrastructure.Utils / ToolsAESUtilMd5UtilDESUtilSM4UtilToolHelper
Middleware/...Infrastructure.MiddlewareEncryptionMiddleware
BasicAuthentication/...Infrastructure.BasicAuthenticationBasic 认证
IpRateLimiting/...Infrastructure.IpRateLimitingAddIpRateLimiting
Filters/...Infrastructure.FiltersSensitiveDataAttributeExceptionNotifier
Google/...Infrastructure.GooglereCAPTCHA
Cap/...Infrastructure.CapCAP 事务扩展
Common/ Extensions/ AspNetCore/ Serilog/ ApiClient/对应命名空间文件/HTTP/CAP 扩展、Autofac、日志、本地化等

Controller 基类

KitApiControllerBase

最底层基类,完全为空(仅 [ApiController]),不需要认证:

[ApiController]
public abstract class KitApiControllerBase : ControllerBase { }

FreeKitController

[Authorize] 的基类,大多数控制器继承它。它没有泛型变体,也不注入任何成员;认证 scheme 由全局 DefaultPolicy 统一管理。当前用户通过 ControllerBase.User 或从 DI 解析 ICurrentUser 获取。

[Authorize]
public abstract class FreeKitController : KitApiControllerBase { }
// 需要认证的 API
[ApiController]
[Route("api/[controller]")]
public class ArticleController : FreeKitController
{
private readonly IArticleService _articleService;
public ArticleController(IArticleService articleService) => _articleService = articleService;

[HttpGet]
public async Task<IActionResult> GetList() => Ok(await _articleService.GetListAsync());
}

// 不需要认证的 API
[ApiController]
[Route("api/[controller]")]
public class PublicController : KitApiControllerBase
{
[HttpGet("health")]
public IActionResult Health() => Ok("ok");
}

应用服务基类

ApplicationService

提供常用服务的懒加载注入(通过 IServiceProvider.GetRequiredService)。

属性类型可见性
CapPublisherDotNetCore.CAP.ICapPublisherpublic
MediatorMediatR.IMediatorpublic
ServiceProviderIServiceProviderpublic
CurrentUserIGeekFan.FreeKit.Extras.Security.ICurrentUserpublic
UnitOfWorkManagerFreeSql.UnitOfWorkManagerpublic
LoggerFactoryILoggerFactorypublic
AuthorizationServiceIAuthorizationServicepublic
LoggerILoggerprotected
PermissionStoreIPermissionStoreprotected

方法:GetEffectiveUserIdAsync(string permission, Guid? queryUserId)(取"有效用户"——支持模拟登录场景)、CurrentUnitOfWork(protected)、LazyGetRequiredService<T>(ref T)

public class ArticleService : ApplicationService, IArticleService
{
private readonly IArticleRepository _repository;
public ArticleService(IArticleRepository repository) => _repository = repository;

public async Task<List<ArticleDto>> GetListAsync()
{
var userId = CurrentUser.FindUserId(); // ICurrentUser 扩展
var articles = await _repository.GetListAsync();
return articles.Adapt<List<ArticleDto>>(); // Mapster 映射
}
}

CrudAppService

CRUD 应用服务模板。泛型参数顺序固定为 7 个

public class ArticleCrudService : CrudAppService<
Article, // 1. TEntity
ArticleDto, // 2. TGetOutputDto (用于 Get/单条)
ArticleListDto, // 3. TGetListOutputDto (用于列表)
Guid, // 4. TKey
ArticleListQuery, // 5. TGetListQuery (通常是 PageQuery 子类)
CreateArticleRequest, // 6. TCreateReq
UpdateArticleRequest // 7. TUpdateReq
>, IArticleCrudService
{
public ArticleCrudService(IBaseRepository<Article, Guid> repository) : base(repository) { }
}

// 自动获得:GetListAsync / GetAsync / CreateAsync / UpdateAsync / DeleteAsync

接口约束:TGetOutputDto : IEntityDto<TKey>TGetListOutputDto : class, IEntityDto<TKey>GetListAsync(TGetListQuery) 返回 PagedResultDto<TGetListOutputDto>(来自 IGeekFan.FreeKit.Extras.Dto)。

可重写的 protected virtual 方法(用于自定义行为):

方法签名
CreateFilteredQueryISelect<TEntity> CreateFilteredQuery(TGetListQuery query)
ApplySortingISelect<TEntity> ApplySorting(ISelect<TEntity> query, TGetListQuery input)
MapToGetListOutputDtoTGetListOutputDto MapToGetListOutputDto(TEntity entity)(默认 entity.Adapt<TGetListOutputDto>()
EntityListToDtoListList<TGetListOutputDto> EntityListToDtoList(IList<TEntity>, TGetListQuery)
EntityListToDtoListAsyncValueTask<List<TGetListOutputDto>> EntityListToDtoListAsync(IList<TEntity>, TGetListQuery)
GetEntityByIdAsyncTask<TEntity> GetEntityByIdAsync(TKey id) / GetEntityByIdAsync(TKey id, bool throwEx, bool validateCurrentUser = false)
ValidateEntityPermissionsvoid ValidateEntityPermissions(TKey id, bool throwEx, bool validateCurrentUser, TEntity entity)
CreateAsyncTask<TGetOutputDto> CreateAsync(TEntity entity, TCreateReq createReq)

:::caution 易错点

  • 不存在 MapToEntity / MapToEntityList / CreateEntityAsync / UpdateEntityAsync / DeleteEntityAsync 这类钩子;实体↔DTO 映射统一用 Mapsterentity.Adapt<T>() / dto.Adapt(entity)
  • 不存在非泛型的 CrudAppServiceBaseCrudAppService<> 本身就是唯一基类。
  • 不存在 PagerListDto<T>;列表分页统一返回 PagedResultDto<T>。 :::

领域服务基类

DomainService

public class DomainService : IDomainService // IDomainService : IScopedDependency
{
public IServiceProvider ServiceProvider { get; set; }
public ICurrentUser CurrentUser { get; } // public
public UnitOfWorkManager UnitOfWorkManager { get; } // public
public ILoggerFactory LoggerFactory { get; }
public IAuthorizationService AuthorizationService { get; }
protected ILogger Logger { get; }
protected IUnitOfWork CurrentUnitOfWork { get; }
}

ApplicationService 相比,DomainService 没有 CapPublisherMediatorPermissionStore——它专注于领域逻辑与聚合根,不直接发分布式事件。

领域事件分发

public interface IDomainEventDispatcher
{
Task DispatchAndClearEvents(IEnumerable<IDomainEventBase> entitiesWithEvents);
}

DomainEventDispatcher 遍历每个含事件的实体 → 取出 GetDomainEvents()ClearDomainEvents() 清空 → 对每个领域事件 await mediator.Publish(...)(经 MediatR 发布):

public class OrderDomainService : DomainService, IOrderDomainService
{
private readonly IDomainEventDispatcher _eventDispatcher;
public async Task PlaceOrderAsync(Order order)
{
// 业务逻辑...
order.AddDomainEvent(new OrderPlacedEvent(order.Id));
await _eventDispatcher.DispatchAndClearEvents(new IDomainEventBase[] { order });
}
}

缓存系统

两种缓存策略

public enum CacheStrategyType { Redis = 0, Memory = 1 } // Redis 为默认

ICacheService

public interface ICacheService
{
T CacheShell<T>(string key, int timeoutSeconds, Func<T> getData);
Task<T> CacheShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getData);
Task<T?> GetAsync<T>(string key);
void Set<T>(string key, int timeoutSeconds, T value);
Task SetAsync<T>(string key, int timeoutSeconds, T value);
void Remove(string key);
void RemoveByPrefix(string prefix);
}

CacheService 默认实现基于 FreeRedis 的 IRedisClienttimeoutSeconds == 0 时直接执行 getData() 不缓存)。

注册

// 无参:注册 RedisCacheProvider / MemoryCacheProvider / CacheProviderFactory(均为 Singleton)
builder.Services.AddCacheStrategy();
警告

源码中没有 AddCacheStrategy(CacheStrategyType.Redis) 这种带参重载,也没有强类型 CacheOptions 类。缓存开关与默认过期通过配置读取:"Cache:Enable"(bool,默认 false)、"Cache:ExpireSeconds"(int,默认 -1)。

使用方式

// 同步壳
var article = _cache.CacheShell("article:" + id, 300, () => _repository.Find(id));

// 异步壳
var article = await _cache.CacheShellAsync("article:" + id, 300, async () => await _repository.FindAsync(id));

[Cacheable] 特性

[AttributeUsage(AttributeTargets.Method)],属性:CacheKey(默认 null)、ExpireSeconds(默认 0)、CacheStrategy(默认 Redis)。

[Cacheable(CacheKey = "article:detail", ExpireSeconds = 300)]
public async Task<Article> GetByIdAsync(Guid id) => await _repository.FindAsync(id);

异常体系

BusinessException

[Serializable]
public class BusinessException : Exception
{
public int StatusCode { get; set; }
public int? Code { get; set; }
public BusinessException WithCode(int? code);
public BusinessException WithStatusCode(int statusCode);
public BusinessException WithData(string name, object value);
}

其基类 CustomException 还提供 ErrorMessages(只读)、StatusCode(默认 InternalServerError)。

常用异常

throw new BusinessException("订单状态不允许操作");
throw new BusinessException("业务错误").WithCode((int)ResponseCode.BusinessException);
throw new EntityNotFoundException(typeof(Article), id);
throw new BadRequestException("参数无效");
throw new InvalidEmailException(email);
throw new InvalidDateException(date);
异常类说明
BusinessException业务异常,带 Code / StatusCode
EntityNotFoundException实体不存在(携带 EntityType / Id
BadRequestException请求参数错误
InvalidEmailException / InvalidDateException邮箱 / 日期格式校验失败

:::caution 已知问题 BadRequestException 当前把 StatusCode 设为 HttpStatusCode.NotFound(404)而非 400,属疑似 bug。若依赖其 HTTP 状态码,请留意。 :::

Guard(基于 Ardalis.GuardClauses)

GuardExtensionsIGuardClause 的扩展方法,调用方式为 Guard.Against.*

Guard.Against.NegativeOrZero(amount, nameof(amount));
Guard.Against.Null(order, nameof(order));
Guard.Against.NotFound(id, nameof(id));

常用方法:Null / NullOrEmpty / NullOrWhiteSpaceNegativeOrZero(decimal/int/long/double)、NegativeNotExistsNotFoundInvalidDateInvalidEmailInvalidCurrencyInvalidPhoneNumber

ResponseCode 枚举(完整)

说明
Success = 0成功
BusinessException = 1001业务异常
Failed = 1002失败
UnknownError = 1007未知错误
ServerUnknownError = 999服务端未知错误
AuthenticationFailed = 10000认证失败
NoPermission = 10001无权限
RefreshTokenError = 10100刷新令牌错误
NotFound = 10020资源不存在(描述"资源不存在")
ParameterError = 10030参数错误(描述"参数错误")
TokenInvalidation = 10040令牌失效(描述"令牌失效")
TokenExpired = 10050Token 过期
RepeatField = 10060字段重复
Inoperable = 10070不可操作
ManyRequests = 10140请求过多
BadFileToken = 40001文件令牌错误

统一响应 ApiResponse

public static ApiResponse Ok(string? message = "操作成功");
public static ApiResponse Failed(string? message = "操作失败");
public static ApiResponse New(ResponseCode errorCode, string? message);
public static ApiResponse<T> Ok<T>(T data, string? message = "操作成功") where T : class;
public static ApiResponse<T> Failed<T>(string? message = "操作成功") where T : class;
return Ok(ApiResponse.Ok(data));
return BadRequest(ApiResponse.Failed("错误信息"));
throw new BusinessException(ResponseCode.BusinessException, "业务错误");

授权与认证

认证模式

public enum AuthMode { Jwt = 0, OpenIddict = 1 }

JwtSettings 模型

public class JwtSettings
{
public string Audience { get; }
public DateTime ExpiresTime { get; set; } // 默认 86400 秒(1 天)
public string Issuer { get; }
public SecurityKey SecurityKey { get; }
public TokenValidationParameters TokenValidationParameters { get; }
}

由配置构造(典型键:JwtSettings:Issuer / JwtSettings:Audience / JwtSettings:ExpiresTime;密钥经 SecurityKey 注入)。具体配置键名以 JwtSettings 的绑定为准。

CookieJwtBearerHandler

CookieJwtBearerHandler : JwtBearerHandler,支持三种 Token 来源(按顺序):

  1. Query?access_token=...)——仅当请求路径以 /hubs 开头时(SignalR Hub 等无法设请求头的场景);
  2. Authorization header——标准 Bearer
  3. Cookieaccess_token)——浏览器会话。

要求 JWT alg 为 HS256,验证参数取自 JwtSettings.TokenValidationParameters

KitAuthorize 特性

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class KitAuthorizeAttribute(string permission, string module) : Attribute, IAsyncAuthorizationFilter
{
public string Permission { get; set; }
public string Module { get; set; }
}

先校验 ValidTokenRequirement(失败 → UnauthorizedResult),再校验 ValidPermissionRequirement(Permission)(失败 → ForbidResult)。

[KitAuthorize("Article.Create", "CmsKit")]
public IActionResult Create() { /* ... */ }

权限存储

public interface IPermissionStore
{
Task<bool> CheckPermissionAsync(string permission);
Task<bool> CheckAccessTokenAsync(string accessToken);
}

注意:源码中只有 IPermissionStore没有 IPermissionChecker / PermissionChecker

授权结果处理

KitAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler 会把未登录 → ResponseCode.AuthenticationFailed(401)、Token 失效 → TokenExpired(401)、无权限 → NoPermission(403),从而让 API 响应与 ResponseCode 体系一致。


中间件

加密中间件

public class EncryptionSettings
{
public bool Enable { get; set; } = false;
public string? EncryptionKey { get; set; }
public string? EncryptionIV { get; set; }
}

EncryptionMiddlewareEnable==true 时,将 JSON 响应体用 CryptoUtil.Encrypt 加密后包成 {"data": "<密文>"}。注册方式:

// 注意:没有 UseEncryption() 扩展,需显式 UseMiddleware
app.UseMiddleware<EncryptionMiddleware>();
{
"Encryption": { "Enable": true, "EncryptionKey": "your-key", "EncryptionIV": "your-iv" }
}
警告

源码中没有 app.UseEncryption() 扩展方法,只有 EncryptionMiddleware 类本身;请使用 app.UseMiddleware<EncryptionMiddleware>()

Basic 认证(保护 Swagger 等)

app.UseBasicAuthentication();
public class BasicAuthenticationOption : AuthenticationSchemeOptions
{
public bool Enable { get; set; } = false;
public List<string>? ProtectPaths { get; set; }
public string? Realm { get; set; }
public string? UserName { get; set; }
public string? UserPassword { get; set; }
}

仅当 Enable==trueProtectPaths 非空时,才对匹配路径启用 Basic 认证。

{
"Basic": { "Enable": true, "ProtectPaths": ["/swagger"], "UserName": "admin", "UserPassword": "123456" }
}

IP 限流

builder.Services.AddIpRateLimiting(builder.Configuration);

底层绑定 AspNetCoreRateLimitIpRateLimitOptions / IpRateLimitPolicies(配置节 IpRateLimiting)。没有 FreeKit 自定义的限流选项类,参数含义与默认值以 AspNetCoreRateLimit 为准。


过滤器与特性

SensitiveDataAttribute(数据脱敏)

[AttributeUsage(AttributeTargets.Property)]
public class SensitiveDataAttribute : Attribute
{
public bool IsSensitive { get; set; } = false; // 唯一属性
}
public class UserDto
{
[SensitiveData(IsSensitive = true)]
public string Phone { get; set; } // 序列化时按规则脱敏
}
警告

SensitiveDataAttribute 只有 IsSensitive 一个属性,没有 Mask 之类的自定义掩码属性。

RecaptchaVerifyActionFilter(reCAPTCHA)

[ServiceFilter(typeof(RecaptchaVerifyActionFilter))]
[HttpPost]
public IActionResult Submit(SubmitRequest request) { /* 自动验证 reCAPTCHA */ }
builder.Services.AddGooglereCaptchav3(builder.Configuration);
// 选项类 GooglereCAPTCHAOptions:Enabled(默认 false)、HeaderKey("Google-RecaptchaToken")、Version(V3)、MinimumScore(0.9F)

异常通知 ExceptionNotifier

支持三通道告警(邮件 / 飞书 / 企业微信),由 IExceptionNotifier.NotifyAsync(Exception) 触发。

public class ExceptionNotifyOptions // SectionName = "ExceptionNotify"
{
public bool Enabled { get; set; } = false;
public MailNotifyOptions Mail { get; set; } // Enabled(默认 false)、MailTo
public WebhookChannelOptions Feishu { get; set; } // Enabled(默认 false)、WebhookUrl、Secret
public WebhookChannelOptions WeCom { get; set; } // Enabled(默认 false)、WebhookUrl、Secret
}
警告

源码中没有名为 ExceptionNotifyFilter 的过滤器类,异常通知能力由 IExceptionNotifier / ExceptionNotifier 提供(通常由全局异常过滤器在捕获后调用)。


安全工具

AES 加密

public static class AESUtil
{
public static string Encrypt(string source, string key, string iv = "",
PaddingMode padding = PaddingMode.PKCS7, CipherMode mode = CipherMode.ECB);
public static string Decrypt(string source, string key, string iv = "",
PaddingMode padding = PaddingMode.PKCS7, CipherMode mode = CipherMode.CBC);
// 另提供接受 AESInput 对象的重载
}
警告

Encrypt 默认 CipherMode.ECB,而 Decrypt 默认 CipherMode.CBC——加解密默认的 mode 不一致,调用时务必显式指定一致的 modeiv

DES 加密

public class DESUtil
{
public static string Encrypt(string sourceString, string Key, string Iv = "12345678",
PaddingMode padding = PaddingMode.PKCS7, CipherMode mode = CipherMode.CBC);
public static string Decrypt(string encryptedString, string Key, string Iv = "12345678", ...);
}

Key 必须为 8 位(不足抛 ArgumentException,超长截断);Iv 默认 "12345678"

SM4 国密

public class SM4Util
{
public static byte[] GenerateKey();
public static byte[] Encrypt_CBC_Padding(byte[] key, byte[] iv, byte[] data);
public static byte[] Decrypt_CBC_Padding(byte[] key, byte[] iv, byte[] cipherText);
public static byte[] Encrypt_ECB_Padding(string key, string data); // 也提供 byte[]/NoPadding 重载
public static byte[] Decrypt_ECB_Padding(string key, string cipherText, Base64OrHexEnum type = Base64OrHexEnum.Hex);
}

注意:CBC 系列方法参数为 byte[](密钥/IV/数据),而非字符串。

MD5 哈希

public class Md5Util
{
public static string Md5Hash(string source); // 32 位大写
public static bool VerifyMd5(string mdPwd, string source); // 大小写不敏感比较
public static string Md5(string soureString, MD5Digit mD5Digit = MD5Digit.Digit32);
public static string Md5ToBase64(string s, MD5Digit mD5Digit = MD5Digit.Digit32);
}
// MD5Digit : Digit16 = 16, Digit32 = 32

Md5Md5Hash 两套方法都存在;Md5Hash / VerifyMd5 是推荐的确定性哈希(可作缓存键)写法。

Base64 与文件

ToolHelper.Base64Encode(content); // UTF8 → Base64
ToolHelper.Base64Decode(content); // Base64 → UTF8
// 另含:FileToHashBase64String / GetFileMD5Hash / GetFileSHA256Hash 等

数据脱敏

var masked = MaskHelper.MaskPhoneNumber("13812345678"); // "138****5678"

CryptoUtil(遗留)

CryptoUtil.Encrypt/Decrypt/EncryptRequestData/ImgDecryptApi 含硬编码密钥,仅用于特定历史兼容,建议新代码勿依赖。


DTO 基类

ApiResponse

public class ApiResponse : IApiResponse
{
public int Code { get; set; }
public string? Message { get; set; }
public static ApiResponse Ok(string? message = "操作成功");
public static ApiResponse Failed(string? message = "操作失败");
public static ApiResponse New(ResponseCode errorCode, string? message);
public static ApiResponse<T> Ok<T>(T data, string? message = "操作成功") where T : class;
public static ApiResponse<T> Failed<T>(string? message = "操作成功") where T : class;
}
public class ApiResponse<T> : ApiResponse, IApiResponse<T> where T : class
{
public T Data { get; set; }
}

PageQuery

public class PageQuery : BasePagingInfo, ISortedResultRequest, IValidatableObject
{
public const int MaxPageSize = 50;
// 默认:PageNumber=1, PageSize=30, Sorting="Id desc", IsQueryCount=true
public string? Sorting { get; set; }
public bool? IsQueryCount { get; set; }
}

验证规则:PageNumber >= 1PageSize >= 1PageSize <= 50。分页列表结果统一返回 PagedResultDto<T>(来自 IGeekFan.FreeKit.Extras.Dto)。

public class ArticleListQuery : PageQuery
{
public string? Keyword { get; set; }
}

[HttpGet]
public async Task<PagedResultDto<ArticleDto>> GetList(ArticleListQuery query)
=> await _articleService.GetListAsync(query);

其它

  • ISortedResultRequeststring? Sorting { get; set; }(支持 "Name ASC, Age DESC" 风格)。
  • EnumDto.FromEnum<T>():把枚举转为 List<EnumDto>Value / Label)。

扩展方法

分页(E 静态类)

public static Task<List<TEntity>> ToPagerListAsync<TEntity>(this ISelect<TEntity> source, PageQuery pageQuery);
public static List<TEntity> ToPagerList<TEntity>(this ISelect<TEntity> source, PageQuery pageQuery);
public static ISelect<TEntity> ApplyPage<TEntity>(this ISelect<TEntity> source, PageQuery pageQuery);

IsQueryCount==false 时设 Count=-1 并仅 Skip/Take

文件(IFileProvider / IFileInfo)

var files = fileProvider.GetFilesRecursively("Templates"); // IEnumerable<(string, IFileInfo)>
var content = await fileInfo.ReadAsStringAsync(Encoding.UTF8);

CAP 分布式事务

// 开启事务(返回 MySqlCapTransaction,绑定 FreeSql 事务)
ICapTransaction tx = unitOfWork.BeginTransaction(publisher, autoCommit: false);
// 提交:先 unitOfWork.Commit() 再 tx.Flush()
tx.Commit(unitOfWork);

// 服务注册
services.AddKitCap(configuration, assemblies); // 绑定 ConnectionStrings,注册 MySQL+RabbitMQ 等

当前用户扩展(CurrentUserExtensions)

CurrentUser.FindUserId(); // Guid(找不到返回 Guid.Empty)
CurrentUser.FindUserIdThrowException(); // 未登录抛异常
CurrentUser.IsAdmin(); // IsInRole("Admin")
CurrentUser.IsImpersonating(); // 是否处于模拟登录
CurrentUser.FindImpersonatorUserId(); // 模拟者 Id
CurrentUser.FindImpersonatorUserName();
CurrentUser.FindOriginalTenantId(); // 模拟前的原始租户
CurrentUser.GetActorDisplayName();

Autofac 领域服务注册

containerBuilder.RegisterDomainServices(typeof(SomeModule).Assembly); // 批量注册 IDomainService

依赖关系

InfrastructureBuildingBlocks 的基础;WebAuth.Client 建立在它之上(见 building-blocks 总览)。

相关文档