Skip to content

Commit

Permalink
优化wrapper添加的细节; v1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
stratosblue committed Oct 23, 2022
1 parent 4514df8 commit 70419cb
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<IsPackable>true</IsPackable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

<Version>1.1.0-beta001</Version>
<Version>1.1.0</Version>
<Description>用于`asp.net core`的响应和异常自动包装器,使`Action`提供一致的响应内容格式</Description>

<PackageIdPrefix>Cuture.AspNetCore.ResponseAutoWrapper</PackageIdPrefix>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,38 +84,55 @@ public WrapperBuilder<TResponse, TCode, TMessage> AddLegacyWrappers<TLegacyCompa
}

/// <summary>
/// 添加一个 Wrapper
/// 检查 <typeparamref name="TWrapper"/> 实现的包装接口,将其添加为对应的包装器
/// </summary>
/// <typeparam name="TWrapper"></typeparam>
/// <param name="lifetime">注册DI容器的生命周期</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public WrapperBuilder<TResponse, TCode, TMessage> AddWrapper<TWrapper>(ServiceLifetime lifetime = ServiceLifetime.Singleton) where TWrapper : IWrapper<TResponse, TCode, TMessage>
public WrapperBuilder<TResponse, TCode, TMessage> AddWrapper<TWrapper>(ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TWrapper : IWrapper<TResponse, TCode, TMessage>
{
var wrapperType = typeof(TWrapper);
Type serviceType;
if (wrapperType.IsAssignableTo(typeof(IActionResultWrapper<TResponse, TCode, TMessage>)))
bool hasAdded = false;
if (TryAddWrapper<TWrapper, IActionResultWrapper<TResponse, TCode, TMessage>>(lifetime))
{
serviceType = typeof(IActionResultWrapper<TResponse, TCode, TMessage>);
hasAdded = true;
}
else if (wrapperType.IsAssignableTo(typeof(IExceptionWrapper<TResponse, TCode, TMessage>)))
if (TryAddWrapper<TWrapper, IExceptionWrapper<TResponse, TCode, TMessage>>(lifetime))
{
serviceType = typeof(IExceptionWrapper<TResponse, TCode, TMessage>);
hasAdded = true;
}
else if (wrapperType.IsAssignableTo(typeof(IInvalidModelStateWrapper<TResponse, TCode, TMessage>)))
if (TryAddWrapper<TWrapper, IInvalidModelStateWrapper<TResponse, TCode, TMessage>>(lifetime))
{
serviceType = typeof(IInvalidModelStateWrapper<TResponse, TCode, TMessage>);
hasAdded = true;
}
else if (wrapperType.IsAssignableTo(typeof(INotOKStatusCodeWrapper<TResponse, TCode, TMessage>)))
if (TryAddWrapper<TWrapper, INotOKStatusCodeWrapper<TResponse, TCode, TMessage>>(lifetime))
{
serviceType = typeof(INotOKStatusCodeWrapper<TResponse, TCode, TMessage>);
hasAdded = true;
}
else
if (!hasAdded)
{
throw new ArgumentException($"{wrapperType} not implemented any available wrapper interface for response type {typeof(TResponse)}.");
throw new ArgumentException($"{typeof(TWrapper)} not implemented any available wrapper interface for response type {typeof(TResponse)}.");
}
return this;
}

_services.TryAddEnumerable(ServiceDescriptor.Describe(serviceType, wrapperType, lifetime));
/// <summary>
/// 将 <typeparamref name="TWrapper"/> 添加为 <typeparamref name="TWrapperInterface"/> 包装器
/// </summary>
/// <typeparam name="TWrapper"></typeparam>
/// <typeparam name="TWrapperInterface"></typeparam>
/// <param name="lifetime">注册DI容器的生命周期</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public WrapperBuilder<TResponse, TCode, TMessage> AddWrapper<TWrapper, TWrapperInterface>(ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TWrapper : IWrapper<TResponse, TCode, TMessage>, TWrapperInterface
where TWrapperInterface : IWrapper<TResponse, TCode, TMessage>
{
if (!TryAddWrapper<TWrapper, TWrapperInterface>(lifetime))
{
throw new ArgumentException($"{typeof(TWrapper)} not implemented wrapper interface {typeof(TWrapperInterface)} for response type {typeof(TResponse)}.");
}

return this;
}
Expand All @@ -124,13 +141,37 @@ public WrapperBuilder<TResponse, TCode, TMessage> AddWrapper<TWrapper>(ServiceLi
/// 尝试将派生自 <see cref="AbstractResponseWrapper{TResponse, TCode, TMessage}"/> 的类添加为多个 Wrapper
/// </summary>
/// <typeparam name="TWrapper"></typeparam>
/// <param name="lifetime">注册DI容器的生命周期</param>
/// <returns></returns>
public WrapperBuilder<TResponse, TCode, TMessage> AddWrappers<TWrapper>() where TWrapper : AbstractResponseWrapper<TResponse, TCode, TMessage>
public WrapperBuilder<TResponse, TCode, TMessage> AddWrappers<TWrapper>(ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TWrapper : AbstractResponseWrapper<TResponse, TCode, TMessage>
{
_services.TryAddWrapper<TWrapper, TResponse, TCode, TMessage>();
_services.TryAddWrapper<TWrapper, TResponse, TCode, TMessage>(lifetime);
return this;
}

/// <summary>
/// 尝试将 <typeparamref name="TWrapper"/> 添加为 <typeparamref name="TWrapperInterface"/> 包装器
/// </summary>
/// <typeparam name="TWrapper"></typeparam>
/// <typeparam name="TWrapperInterface"></typeparam>
/// <param name="lifetime">注册DI容器的生命周期</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public bool TryAddWrapper<TWrapper, TWrapperInterface>(ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TWrapper : IWrapper<TResponse, TCode, TMessage>
where TWrapperInterface : IWrapper<TResponse, TCode, TMessage>
{
var wrapperType = typeof(TWrapper);
if (wrapperType.IsAssignableTo(typeof(IActionResultWrapper<TResponse, TCode, TMessage>)))
{
_services.TryAddEnumerable(ServiceDescriptor.Describe(typeof(TWrapperInterface), wrapperType, lifetime));
return true;
}

return false;
}

#endregion Public 方法
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ public static IResponseAutoWrapperBuilder<TResponse, TCode, TMessage> AddRespons

#region Internal 方法

internal static void TryAddWrapper<TResponseWrapper, TResponse, TCode, TMessage>(this IServiceCollection services)
internal static void TryAddWrapper<TResponseWrapper, TResponse, TCode, TMessage>(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TResponseWrapper : AbstractResponseWrapper<TResponse, TCode, TMessage>
where TResponse : class
{
static TResponseWrapper GetDefaultResponseWrapper(IServiceProvider serviceProvider) => serviceProvider.GetRequiredService<TResponseWrapper>();

services.TryAddSingleton<TResponseWrapper>();
services.TryAddSingleton<IActionResultWrapper<TResponse, TCode, TMessage>>(GetDefaultResponseWrapper);
services.TryAddSingleton<IExceptionWrapper<TResponse, TCode, TMessage>>(GetDefaultResponseWrapper);
services.TryAddSingleton<INotOKStatusCodeWrapper<TResponse, TCode, TMessage>>(GetDefaultResponseWrapper);
services.TryAddSingleton<IInvalidModelStateWrapper<TResponse, TCode, TMessage>>(GetDefaultResponseWrapper);
services.TryAdd(ServiceDescriptor.Describe(typeof(TResponseWrapper), typeof(TResponseWrapper), lifetime));
services.TryAdd(ServiceDescriptor.Describe(typeof(IActionResultWrapper<TResponse, TCode, TMessage>), GetDefaultResponseWrapper, lifetime));
services.TryAdd(ServiceDescriptor.Describe(typeof(IExceptionWrapper<TResponse, TCode, TMessage>), GetDefaultResponseWrapper, lifetime));
services.TryAdd(ServiceDescriptor.Describe(typeof(INotOKStatusCodeWrapper<TResponse, TCode, TMessage>), GetDefaultResponseWrapper, lifetime));
services.TryAdd(ServiceDescriptor.Describe(typeof(IInvalidModelStateWrapper<TResponse, TCode, TMessage>), GetDefaultResponseWrapper, lifetime));
}

#endregion Internal 方法
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ public class ResponseAutoWrapMiddlewareOptions

/// <summary>
/// 默认输出格式化器选择委托<para/>
/// 选择在请求中无 Accept 时,用于格式化响应的 <see cref="IOutputFormatter"/>
/// 选择在请求中无 Accept 时,用于格式化响应的 <see cref="IOutputFormatter"/><para/>
/// 默认时会选择 <see cref="SystemTextJsonOutputFormatter"/> ,不存在则会抛出异常
/// </summary>
public Func<FormatterCollection<IOutputFormatter>, IOutputFormatter> DefaultOutputFormatterSelector { get; set; }
= static formatters => formatters.FirstOrDefault(m => m.GetType() == typeof(SystemTextJsonOutputFormatter))
?? throw new InvalidOperationException($"Can not found {nameof(SystemTextJsonOutputFormatter)} by default. Must select a formatter manually.");
?? throw new InvalidOperationException($"Can not found {nameof(SystemTextJsonOutputFormatter)} by default. Must select a formatter manually by \"{nameof(ResponseAutoWrapMiddlewareOptions)}.{nameof(DefaultOutputFormatterSelector)}\" at middleware setup.");

/// <summary>
/// 是否将捕获到的异常抛出给上层中间件<para/>
Expand Down

0 comments on commit 70419cb

Please sign in to comment.