我的控制器在mvc中更新用户状态的操作:
public class UserController : AdminController
{
public async Task UpdateUserStatus(int id, int status)
{
await UpdateTheStatus<UserService, User>(id, status);
}
}
我有一个基本控制器来更新用户状态
public abstract class AdminController : ControllerBase
{
public async Task UpdateTheStatus<TService, T>(int id, int status)
where TService : StatusService<T>, new()
{
await new TService().UpdateStatus(id, status);
}
}
我的UserService.cs
具有构造函数
public class UserService : StatusService<User>
{
public UserService(MyContext context) : base(context)
{
}
....
}
基类StatusService.cs
public abstract class StatusService<T>
{
protected MyContext ctx = null;
public StatusService(MyContext context)
{
ctx = context;
}
public async virtual Task UpdateStatus(int id, int status)
{
...
await ctx.SaveChangesAsync();
}
}
然后我的代码出现错误:
'UserService' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TService' in the generic type or method
如何将参数作为泛型类型传递给构造函数?
您的基本问题是,只要您使用的是UserService
对象,就需要在要创建TService
的位置上创建MyContext
的实例。
解决此问题的一种方法是将Func<TService>
传递给UpdateStatus()
方法,而不是指定new
约束:
public async Task UpdateStatus<TService, T>(int id, int status, Func<TService> serviceCreator)
where TService : StatusService<T>
{
await serviceCreator().UpdateStatus(id, status);
}
那么UpdateUserStatus()
的实现看起来是这样的:
public async Task UpdateUserStatus(int id, int status)
{
var context = new MyContext(); // However you obtain this.
await UpdateStatus<UserService, User>(id, status, () => new UserService(context));
}
然后面临的问题是如何获得创建UserService
对象所需的MyContext
实例。您无法避免对MyContext
实例的需要,因为UserService
在创建它时需要它。
下面是一个关于DotNetFiddle的可运行示例。
您可以进一步注入用于创建MyContext
对象的委托:
public async Task UpdateUserStatus(int id, int status, Func<MyContext> contextProvider)
{
await UpdateStatus<UserService, User>(id, status, () => new UserService(contextProvider()));
}
现在,我们已经将MyContext
的创建推向了外部级别。当然,外部级别必须仍然能够获得或创建MyContext
。
下面是一个在DotNetFiddle上进行这些更改的可运行示例。
看起来你已经设置好在项目中使用DI,所以你应该使用它。
在Program.cs中,注册实现基类的类(作为接口可能会更好(,例如:
builder.Services.AddTransient<StatusService<User>, UserService>();
现在,不需要单独的任务来更新状态,只需通过DI将您期望的服务传递到构造函数中,DI将自动包括上下文:
public class WhatIsYourClassCalled
{
private readonly StatusService<User> _statusService;
public WhatIsYourClassCalled(StatusService<User> statusService)
{
_statusService = statusService;
}
public async Task UpdateUserStatus(int id, int status)
{
await _statusService.UpdateStatus(id, status);
}
}