根据构造函数参数属性使用 autofac 解决依赖关系

发布于 2024-08-25 14:21:00 字数 454 浏览 1 评论 0原文

我正在使用 Autofac。我想根据应用于构造函数参数的属性注入依赖项的不同实现。例如:

class CustomerRepository
{
    public CustomerRepository([CustomerDB] IObjectContainer db) { ... }
}

class FooRepository
{
    public FooRepository([FooDB] IObjectContainer db) { ... }
}

builder.Register(c => /* return different instance based on attribute on the parameter */)
       .As<IObjectContainer>();

属性将提供数据,例如连接字符串,我可以使用它来实例化正确的对象。

我该怎么做?

I'm using Autofac. I want to inject a different implementation of a dependency based on an attribute I apply to the constructor parameter. For example:

class CustomerRepository
{
    public CustomerRepository([CustomerDB] IObjectContainer db) { ... }
}

class FooRepository
{
    public FooRepository([FooDB] IObjectContainer db) { ... }
}

builder.Register(c => /* return different instance based on attribute on the parameter */)
       .As<IObjectContainer>();

The attributes will be providing data, such as a connection string, which I can use to instance the correct object.

How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静赏你的温柔 2024-09-01 14:21:00

听起来您想为 CustomerRepositoryFooRepository 提供 IObjectContainer 的不同实现。如果是这种情况,属性可能是薄金属尺。相反,我将向您展示如何使用 Autofac 实现多个实现。

(为简洁起见,已省略 .ContainerScoped() 等调用。)

首先,通过命名注册为每个连接字符串注册一个 IObjectContainer 版本:

builder
    .Register(c => new ObjectContainer(ConnectionStrings.CustomerDB))
    .As<IObjectContainer>()
    .Named("CustomerObjectContainer");

builder
    .Register(c => new ObjectContainer(ConnectionStrings.FooDB))
    .As<IObjectContainer>()
    .Named("FooObjectContainer");

然后,解析存储库注册中的特定实例:

builder.Register(c => new CustomerRepository(
    c.Resolve<IObjectContainer>("CustomerObjectContainer"));

builder.Register(c => new FooRepository(
    c.Resolve<IObjectContainer>("FooObjectContainer"));

这使得存储库没有配置信息:

class CustomerRepository
{
    public CustomerRepository(IObjectContainer db) { ... }
}

class FooRepository
{
    public FooRepository(IObjectContainer db) { ... }
}

It sounds like you want to provide different implementations of IObjectContainer to CustomerRepository and FooRepository. If that is the case, attributes might be a thin metal ruler. Instead, I'll show you how I would implement multiple implementations with Autofac.

(Calls such as .ContainerScoped() have been left out for brevity.)

First, register a version of IObjectContainer for each connection string by naming the registrations:

builder
    .Register(c => new ObjectContainer(ConnectionStrings.CustomerDB))
    .As<IObjectContainer>()
    .Named("CustomerObjectContainer");

builder
    .Register(c => new ObjectContainer(ConnectionStrings.FooDB))
    .As<IObjectContainer>()
    .Named("FooObjectContainer");

Then, resolve the specific instances in the repository registrations:

builder.Register(c => new CustomerRepository(
    c.Resolve<IObjectContainer>("CustomerObjectContainer"));

builder.Register(c => new FooRepository(
    c.Resolve<IObjectContainer>("FooObjectContainer"));

This leaves the repositories free of configuration information:

class CustomerRepository
{
    public CustomerRepository(IObjectContainer db) { ... }
}

class FooRepository
{
    public FooRepository(IObjectContainer db) { ... }
}
稀香 2024-09-01 14:21:00

当您有多个存储库并且它们的构造函数参数很少时,布莱恩的答案就足够好了。但是当你有很多根时,很难建立你的根。您可以通过扫描解析接口时的类元数据来实现此目的。当您获得有关其参数的信息时,您可以解决它的实际实现。请参阅我的回答此处

Bryan's answer is good enough while you have several repositories and they have few constructor parameters. But it is difficult to set up your root when you have many of them. You can achieve this by scanning your class metadata on resolving an interface. When you get info about its parameters you can resolve actual implementation of it. See my answer here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文