Asp.Net Core控制器一般情况下不使用泛型,因为在控制器初始化时无法确定泛型的具体类型。在有些情况下需要泛型控制器,必须下面这段代码,
[TypeFilter(typeof(ControllerExceptionFilterAttribute))]
[Area("MyAdmin")]
public class ManagementController<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto> : Controller
where TUserDto : UserDto<TKey>, new()
where TRoleDto : RoleDto<TKey>, new()
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
where TUsersDto : UsersDto<TUserDto, TKey>
where TRolesDto : RolesDto<TRoleDto, TKey>
where TUserRolesDto : UserRolesDto<TRoleDto, TKey>
where TUserClaimsDto : UserClaimsDto<TUserClaimDto, TKey>
where TUserProviderDto : UserProviderDto<TKey>
where TUserProvidersDto : UserProvidersDto<TUserProviderDto, TKey>
where TUserChangePasswordDto : UserChangePasswordDto<TKey>
where TRoleClaimsDto : RoleClaimsDto<TRoleClaimDto, TKey>
where TUserClaimDto : UserClaimDto<TKey>
where TRoleClaimDto : RoleClaimDto<TKey>
{
private readonly IIdentityService<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto> _identityService;
public ManagementController(IIdentityService<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto> identityService)
{
_identityService = identityService;
}
由于依赖注入的服务是泛型类型,所以要求泛型控制器,这种情况下,需要在启动时设置泛型控制器。在StartUp中增加下面的代码:
services.AddControllers(o =>
{
o.Conventions.Add(new GenericControllerRouteConvention());
}).ConfigureApplicationPartManager(m =>
{
m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto>());
});
这里为ApplicationPart增加新的控制器属性:
public class GenericTypeControllerFeatureProvider<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto> : IApplicationFeatureProvider<ControllerFeature>
where TUserDto : UserDto<TKey>, new()
where TRoleDto : RoleDto<TKey>, new()
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
where TUsersDto : UsersDto<TUserDto, TKey>
where TRolesDto : RolesDto<TRoleDto, TKey>
where TUserRolesDto : UserRolesDto<TRoleDto, TKey>
where TUserClaimsDto : UserClaimsDto<TUserClaimDto, TKey>
where TUserProviderDto : UserProviderDto<TKey>
where TUserProvidersDto : UserProvidersDto<TUserProviderDto, TKey>
where TUserChangePasswordDto : UserChangePasswordDto<TKey>
where TRoleClaimsDto : RoleClaimsDto<TRoleClaimDto, TKey>
where TUserClaimDto : UserClaimDto<TKey>
where TRoleClaimDto : RoleClaimDto<TKey>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
var currentAssembly = typeof(GenericTypeControllerFeatureProvider<TUserDto, TRoleDto, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto, TUserClaimDto, TRoleClaimDto>).Assembly;
var controllerTypes = currentAssembly.GetExportedTypes()
.Where(t => typeof(ControllerBase).IsAssignableFrom(t) && t.IsGenericTypeDefinition)
.Select(t => t.GetTypeInfo());
var type = this.GetType();
var genericType = type.GetGenericTypeDefinition().GetTypeInfo();
var parameters = genericType.GenericTypeParameters
.Select((p, i) => new { p.Name, Index = i })
.ToDictionary(a => a.Name, a => type.GenericTypeArguments[a.Index]);
foreach (var controllerType in controllerTypes)
{
var typeArguments = controllerType.GenericTypeParameters
.Select(p => parameters[p.Name])
.ToArray();
feature.Controllers.Add(controllerType.MakeGenericType(typeArguments).GetTypeInfo());
}
}
}
这段代码中注册程序集中的泛型控制器。总结一下,需要将自定义类型转换为控制器,需要自定义一个类,继承IApplicationFeatureProvider<ControllerFeature>,在PopulateFeature中,将相关类型增加到控制器中。
网友评论