在ASP.NET Core Web API中的属性和方法注入

huangapple go评论74阅读模式
英文:

Property and method Injection in ASP.NET Core Web API

问题

如何实现属性和方法的依赖注入?如何添加服务?最后,与使用构造函数注入相比,它可以产生多大的影响?

是否可以使用属性/方法注入替代构造函数注入?

.Net初学者在这里,所有的帮助将不胜感激 <3

在我的包装类中,我正在使用构造函数 DI:

private ICustomerRepository _customerRepository; //用于顾客
private ICountryRepository _countryRepository; //用于国家
private IRegionRepository _regionRepository; //用于地区
private ICityRepository _cityRepository; //用于城市

// 构造函数
public RepositoryWrapper(OmniConnectDB context, ICustomerRepository customerRepository, IMapper mapper, ICountryRepository countryRepository, IRegionRepository regionRepository, ICityRepository cityRepository)
{
    _context = context;
    _mapper = mapper;

    _customerRepository = customerRepository;
    _countryRepository = countryRepository;
    _regionRepository = regionRepository;
    _cityRepository = cityRepository;   
}

在服务中:

// 为位置存储库配置 DI
services.AddScoped<ICountryRepository, CountryRepository>();
services.AddScoped<IRegionRepository, RegionRepository>();
services.AddScoped<ICityRepository, CityRepository>();

// 为顾客服务配置 DI
services.AddScoped<ICustomerService, CustomerService>();

请注意,上述内容中的代码部分未被翻译。

英文:

How does one implement property and method dependency injection? How do I add the services? And finally, how good of an impact can that have compared to using constructor injection?

Is it possible to use property/method injection instead of constructor injection?

.Net beginner here and all the help would be appreciated <3

In my wrapper class where I am using constructor DI:

private ICustomerRepository _customerRepository; //For customer
private ICountryRepository _countryRepository; //For country
private IRegionRepository _regionRepository; //for region
private ICityRepository _cityRepository; //for city

// Constructor 
public RepositoryWrapper(OmniConnectDB context, ICustomerRepository customerRepository, IMapper mapper, ICountryRepository countryRepository, IRegionRepository regionRepository, ICityRepository cityRepository)
{
    _context = context;
    _mapper = mapper;

    _customerRepository = customerRepository;
    _countryRepository = countryRepository;
    _regionRepository = regionRepository;
    _cityRepository = cityRepository;   
}

In services:

// configure DI for Location Repositories
services.AddScoped&lt;ICountryRepository, CountryRepository&gt;();
services.AddScoped&lt;IRegionRepository, RegionRepository&gt;();
services.AddScoped&lt;ICityRepository, CityRepository&gt;();

// Configure DI for Customer Service
services.AddScoped&lt;ICustomerService, CustomerService&gt;();

答案1

得分: 4

https://stackoverflow.com/questions/38459625/property-injection-in-asp-net-core 中所解释的,ASP.NET Core 不支持属性注入,但你可以通过扩展如 Quickwire或使用不同的DI/IoC容器(如Autofac)来实现它。

但是:

相对于使用构造函数注入,它能产生多大的影响?

完全没有,但你会面临所有的缺点:类的依赖关系不明显(你无法绕过构造函数),你可能会留下依赖项为空,导致后续错误并妨碍编译时安全性。

我正在遵循仓储设计模式,其中规范是创建“仓储”类。包装的原因是我不必在每个API中创建所有不同用户类的对象[...] https://code-maze.com/net-core-web-development-part4/

这是反模式的反模式。它有点像服务定位器,将Entity Framework提供的所有功能封装成功能更有限、文档更少的等效服务。

因此,不要注入 YourAppDbContext 并访问其成员 DbSet<Foo> Foos { get; set; },而是注入一个 RepositoryWrapper(它和DbContext是相同的东西,但功能更少),然后获得它的 Foos 属性。

跳过这个教程。

英文:

As explained in https://stackoverflow.com/questions/38459625/property-injection-in-asp-net-core, you don't get property injection out of the box, but you can add it through extensions such as Quickwire or by using a different DI/IoC container altogether (such as Autofac).

But:

> how good of an impact can that have compared to using constructor injection?

None whatsoever, but you get all of the drawbacks: a class's dependencies are not obvious (you can't get around a constructor), you can leave dependencies null, causing later errors and hindering compile-time safety.

> I am following the repository design pattern in which the norm is to create "repository" classes. And the reason for the wrapper is so that I don't have to make objects of all my different user classes in every API [...] https://code-maze.com/net-core-web-development-part4/

This is an antipattern of antipatterns. It is kind of like a service locator, wrapping all the functionality that Entity Framework offers in more limited, equal services with less functionality and less documentation.

So instead of injecting an YourAppDbContext and accessing its members DbSet&lt;Foo&gt; Foos { get; set; }, you inject a RepositoryWrapper (which is the same thing as the DbContext, but can do less) and obtain ... its Foos property.

Skip this tutorial.

答案2

得分: 0

.NET Core本身不支持属性和方法的依赖注入。DI中间件仅支持构造函数注入。ASP.NET Core中间件提供了一种形式的操作注入,但仅适用于操作参数。

在此示例中,TodoDb DbContext 被注入。
这是为了支持最小 API,但也有益于控制器操作。

public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content($"当前服务器时间:{dateTime.Now}");
}

然而,这不是DI中间件的功能,不能用于其他类。ASP.NET Core中间件会检查API方法,识别任何注入的服务,并在编译时使用源生成器来询问DI容器。

从逻辑上看,中间件将:

  • 请求DI中间件创建新的控制器实例
  • 检查操作以获取要注入的参数
  • 最后使用绑定和注入的参数调用操作方法。

在某些情况下,可以自动推断FromServices属性。这在绑定源参数推断部分有解释。ASP.NET Core中间件会检查参数类型是否在DI中注册,并自动使用DI。

如果要在其他代码中使用方法注入,您将不得不使用不同的DI容器或编写自己的代码,模仿ASP.NET Core的行为。

英文:

There's no property and method injection in .NET Core itself. The DI middleware supports only constructor injection. The ASP.NET Core middleware does offer a form of action injection, but only for action parameters.

app.MapPost(&quot;/todoitems&quot;, async (Todo todo, TodoDb db) =&gt;
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($&quot;/todoitems/{todo.Id}&quot;, todo);
});

In this example the TodoDb DbContext is injected.
This was added to enable Minimal API support but benefits controller actions as well.

public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content( $&quot;Current server time: {dateTime.Now}&quot;);
}

This isn't a DI middleware feature though and can't be used for other classes. The ASP.NET Core middleware inspects the API methods, identifies any injected services and asks the DI container for instances. I think that's done using source generators at compile time.

Logically, the middleware will:

  • Ask the DI middleware to create a new controller instance
  • Inspect the action for parameters to inject and
  • Finally call the action method with the bound and injected parameters.

The FromServices attribute can be inferred in some cases. This is explained in the section Binding Source Parameter Inference. The ASP.NET Core middleware will check whether any of the parameter types are registered with DI and use DI automatically.

If you want to use method injection for other code you'll have to either use a different DI container or write code that does what ASP.NET Core does itself.

huangapple
  • 本文由 发表于 2023年3月9日 17:53:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75682912.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定