.NET Core 中的依赖注入

Dependency injection in .NET Core

我正在尝试在控制器中创建 class 的实例。但是,我做不到。

控制器代码:

    [HttpPost]
    [Route("connection")]
    public async Task<IActionResult> DoSomething(string firstName, string lastName)
    {
        return new OkObjectResult(new MyClass().ShowData(firstName, lastName));
    }

Class代码:

public interface ISomeInterface
{
    void SomeMethod();
}

public class MyClass
{
    private readonly ISomeInterface _someInterface;

    public MyClass(ISomeInterface someInterface)
    {
        _someInterface = someInterface;
    }

    public Task<bool> ShowData(string firstName, string lastName)
    {
        // some logic
        if (firstName == "Ram")
        {
            ClassOne obj1 = new ClassOne();
            obj1.DoPlus();
        } else if (firstName == "Sam")
        {
            ClassTwo obj1 = new ClassTwo();
            obj1.DoPlus();
        }
        return Task.FromResult(true);
    }
}

另一个界面

public interface IClassOneTwo
{ 
  void DoPlus();
}

public class ClassOne : IClassOneTwo
{ 
  public void DoPlus()
  { }
}

public class ClassTwo : IClassOneTwo
{ 
  public void DoPlus()
  { }
}

如何将 ISomeInterface 注入控制器?另外,如何分离 ClassOne 和 ClassTwo 的实例?我想注册 IClassOneTwo 接口并基于 IF/ELSE 条件,我想获得 ClassOne 或 ClassTwo.

的实例

为了完整起见,您应该在接口后面抽象 MyClass

例如:

public interface IMyClass
{
    Task<bool> ShowData(string firstName, string lastName);
}

并让 MyClass 实施它:

public class MyClass : IMyClass
{
    private readonly ISomeInterface _someInterface;
    public MyClass(ISomeInterface someInterface)
    {
        _someInterface = someInterface;
    }
    public Task<bool> ShowData(string firstName, string lastName)
    {
        // some logic

        return Task.FromResult(true);
    }
}

那么在你的Startup.csclass,ConfigureServices方法中,你应该注册一下:

services.AddTransient<IMyClass, MyClass>();

您还应该注册 ISomeInterface:

services.AddTransient<ISomeInterface, SomeOtherClass>();

然后,在你的控制器中,你应该通过构造函数注入你想要的服务:

public sealed class MyController : ControllerBase
    
    private readonly IMyClass _myClass;

    public MyController(IMyClass myClass)
    {
        _myClass = myClass;
    }

    [HttpPost, Route("connection")]
    public async Task<IActionResult> DoSomething(
        [FromQuery]string firstName, [FromQuery]string lastName)
    {
        return Ok(await _myClass.ShowData(firstName, lastName));
    }
}

编辑添加...

OP 询问如何使 MyClass 或多或少成为可以使用 ISomeInterface 执行操作的实用程序。所以,你还是想注册ISomeInterface到管道:

services.AddTransient<ISomeInterface, SomeOtherClass>();

您可以 MyClass 切换回原来的状态。

如上所示将 ISomeInterface 注入您的控制器,然后将其传递给 MyClass:

public sealed class MyController : ControllerBase
    
    private readonly ISomeInterface _someOtherClass;

    public MyController(ISomeInterface someOtherClass)
    {
        _someOtherClass = someOtherClass;
    }

    [HttpPost, Route("connection")]
    public async Task<IActionResult> DoSomething(
        [FromQuery]string firstName, [FromQuery]string lastName)
    {
        return Ok(await new MyClass(_someOtherClass)
                .ShowData(firstName, lastName));
    }
}

编辑添加(再次)...

所以我认为我们已经弄清了 OP 想要什么。他们想注入两个共享相同接口的服务。有很多方法可以做到这一点。我会坚持使用我过去使用过的那个。

首先,定义一个委托:

public delegate IClassOneTwo MyServiceResolver(string key);

然后在你的Startup.cs中,在ConfigureServices方法中,注册:

services.AddTransient<ClassOne>();
services.AddTransient<ClassTwo>();

请记住,我们在注册时不使用界面。这很重要。

现在我们创建另一个服务,可以解决您想要的服务:

services.AddTransient<MyServiceResolver>(serviceProvider => key =>
{
    switch (key)
    {
        case "Ram":
            return serviceProvider.GetService<ClassOne>();
        case "Sam":
            return serviceProvider.GetService<ClassTwo>();
        default:
            return null; // or throw an exception
    }
});

然后,在您决定注入的任何服务中(为简单起见,我将使用控制器):

public sealed class MyController : ControllerBase
    
    private readonly MyServiceResolver _serviceResolver;

    public MyController(MyServiceResolver serviceResolver)
    {
        _serviceResolver = serviceResolver;
    }

    [HttpPost, Route("connection")]
    public IActionResult DoSomething(
        [FromQuery]string firstName, [FromQuery]string lastName)
    {
        _serviceResolver(firstName).DoPlus();

        return Ok();
    }
}

现在,您的服务将在运行时解析。