[英]Pass constructor with parameter as generic on .NET Core
I have a method to update the user status我有一种更新用户状态的方法
public async Task UpdateStatus<TService, T>(int id, int status)
where TService : StatusService<T>, new()
{
await new TService().UpdateStatus(id, status);
}
My UserService
have constructor我的
UserService
有构造函数
public class UserService : StatusService<User>
{
public UserService(MyContext context) : base(context)
{
}
....
}
Action to update user status:更新用户状态的操作:
public async Task UpdateUserStatus(int id, int status)
{
await UpdateStatus<UserService, User>(id, status);
}
Then my code have the error:然后我的代码有错误:
'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
How do I pass the constructor with parameter as generic type?如何将带有参数的构造函数作为泛型类型传递?
Your fundamental issue is that you need an instance of MyContext
at the point where you want to create the TService
, as long as you are using a UserService
object.您的基本问题是,只要您使用的是
UserService
object,您就需要在要创建MyContext
的位置创建一个TService
实例。
One way to solve this is to pass in a Func<TService>
to the UpdateStatus()
method instead of specifying the new
restraint:解决此问题的一种方法是将
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);
}
Then the implementation of UpdateUserStatus()
would look something like this:然后
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));
}
The issue you then face is how to obtain the MyContext
instance that you need for creating the UserService
object.然后您面临的问题是如何获取创建
UserService
object 所需的MyContext
实例。 You can't avoid the need for the MyContext
instance because the UserService
requires it when you create it.您无法避免需要
MyContext
实例,因为UserService
在您创建它时需要它。
Here's a runnable example on DotNetFiddle.这是 DotNetFiddle 上的一个可运行示例。
You can take a further step of injecting a delegate with which to create the MyContext
object:您可以进一步注入一个委托来创建
MyContext
object:
public async Task UpdateUserStatus(int id, int status, Func<MyContext> contextProvider)
{
await UpdateStatus<UserService, User>(id, status, () => new UserService(contextProvider()));
}
Now we've pushed the MyContext
creation to the outer level.现在我们已经将
MyContext
创建推到了外部级别。 The outer level must still be able to obtain or create a MyContext
, of course.当然,外部级别必须仍然能够获取或创建
MyContext
。
Here's a runnable example with those changes on DotNetFiddle.这是一个可运行的示例,其中包含 DotNetFiddle 上的这些更改。
Looks like you're set up to use DI in your project, so you should use it.看起来您已设置为在项目中使用 DI,因此您应该使用它。
In your Program.cs, register your classes that implement your base class (which could be better as an interface), eg:在您的 Program.cs 中,注册实现基本 class 的类(作为接口可能更好),例如:
builder.Services.AddTransient<StatusService<User>, UserService>();
Now instead of having a separate task to update the status, just pass your expected service into your constructor via DI which will automatically include the context:现在不需要单独的任务来更新状态,只需通过 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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.