Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#asp.net核心注入DbContext而不使用构造函数_C#_Asp.net Core - Fatal编程技术网

C#asp.net核心注入DbContext而不使用构造函数

C#asp.net核心注入DbContext而不使用构造函数,c#,asp.net-core,C#,Asp.net Core,我尝试创建一个BaseController,它应该包含一个DbContest实例 public abstract class BaseODataController<T> : ODataController where T : class { protected readonly ApplicationDbContext _db; public BaseODataController(ApplicationDbContext db) { _d

我尝试创建一个BaseController,它应该包含一个DbContest实例

public abstract class BaseODataController<T> : ODataController where T : class
{
    protected readonly ApplicationDbContext _db;

    public BaseODataController(ApplicationDbContext db)
    {
        _db = db;
    }
}

所以我不必在每个控制器中传递它

ASP.NET核心依赖项注入系统将不会解析基类依赖项。您确实需要通过
base
语句从派生类的构造函数显式地向基类提供依赖关系:

public Foo(ApplicationDbContext db) : base(db)
{
    _db = db;
}
您可以将依赖项解析器存储在静态类中,并直接在基类构造函数中调用它,例如:

_db = Container.Resolver.Resolve<ApplicationDbContext>();
\u db=Container.Resolver.Resolve();

您不需要在派生构造函数中设置字段,但仍然必须在派生类上实现构造函数。这与依赖注入无关;这只是继承在C#中的工作方式。构造函数不是继承的,因此如果您希望派生类具有相同的可用构造函数(为了接受上下文,它将需要相同的构造函数),那么必须在派生类上声明它。但是,您可以简单地将构造逻辑传递给基本构造函数

public abstract class BaseODataController<T> : ODataController
    where T : class
{
    protected readonly ApplicationDbContext _db;

    public BaseODataController(ApplicationDbContext db)
    {
        _db = db;
    }
}

public class FooController : BaseODataController<Foo>
{
    public FooController(ApplicationDbContext context)
        : base(context)
    {
    }
}
公共抽象类BaseODataController:ODataController
T:在哪里上课
{
受保护的只读ApplicationDbContext\u db;
公共BaseODataController(ApplicationDbContext数据库)
{
_db=db;
}
}
公共类FooController:BaseODataController
{
公共FooController(ApplicationDbContext上下文)
:基本(上下文)
{
}
}

@Set不是一个重复的,另一个与基类无关。那么你期望什么呢?什么值将被分配给
\u db
,它从哪里来???@Flo听起来你误解了什么是控制反转和依赖注入。与在控制器中硬编码DbContext的创建过程不同,这使得定制和测试变得非常困难,相反,您可以将其反转并将该依赖项注入构造函数中。这使得测试更加容易,例如允许您传递一个虚拟的或仅内存的DbContext,而不是实际的DbContext。DI容器使创建一个具有所有依赖项的类变得很容易。选项之一是使用更高级的DI库,并使用属性注入而不是构造函数注入。这将允许您使构造函数无参数。但我强烈建议不要这样做,因为我相信如果没有
DbContext
,您的控制器将无法正常工作,因此最好在构造函数中传递此依赖项。当然,但我很懒,希望避免这种情况:P@Flo然后你误解了DI的工作原理。如果该字段受保护,则不必存储它,只需引用基本字段即可field@PanagiotisKanavos派生类是否可以在基类中设置
只读
字段?我不认为我以前试过,不确定一次性初始化规则是否会带入基类。我知道,但是
readonly
意味着它只能由构造函数初始化。我想知道的是,基类的“只读”异常是否会影响派生类(假定派生类可以有不同的构造函数签名)。这不是可见性问题。基本构造函数是构造函数。您可能已经使用过它,尤其是在BCL类中,但没有意识到这一点。实际上,应该是基构造函数初始化基只读字段,而不是派生类。否则,您将面临创建状态无效的对象的风险。这是一个强烈的提示,上下文可能应该是一个只读属性,以防止派生类与ASP.NET Core的DI的正确语法混淆,这也是服务定位器反模式。。。由于他们仍然需要使用DI来获取DI
ServiceProvider
的一个实例,因此您并没有以这种方式保存任何工作。编辑答案以将解析器放入控制器,当然这是一种反模式,但它可以工作。这是服务定位器反模式,DI本应该阻止的事情。@Nagelkopf,但它没有。当你不得不执行所有这些额外的工作来打破内置的机制时,就不会了。我知道,但这回答了问题,OP并没有要求DI解决方案!是的,这就是我目前的做法。那么问题是什么?你只是因为必须重新声明构造函数而感到恼火吗?不幸的是,正如我所说的,这是一个语言限制,所以你必须接受它。好吧,值得一提的是,在VS中,你只需右键单击派生类名,那里有一个选项可以为你实现每个基本构造函数。至少您不必键入它;)真正地没有在mac上使用VS,但这很不幸。他们至少为Mac提供了一个选项,这很好,但总的来说,在windows端,工具可能总是更好。可能值得运行bootcamp和real Visual Studio,具体取决于您主要开发的内容。
public abstract class BaseODataController<T> : ODataController
    where T : class
{
    protected readonly ApplicationDbContext _db;

    public BaseODataController(ApplicationDbContext db)
    {
        _db = db;
    }
}

public class FooController : BaseODataController<Foo>
{
    public FooController(ApplicationDbContext context)
        : base(context)
    {
    }
}