.NET 8 - 如何使用依赖注入来注入两个 MongoDB 客户端

问题描述 投票:0回答:2

如何使用依赖注入 (.NET 8) 注入两个 MongoDB 客户端?我有一个场景,我需要从 Db1/collection1 读取内容,然后将某些内容保存到 Db2/collection2。在我的启动中,我有以下内容,但不确定如何注入第二个

IMongoClient
(两者都有不同的连接字符串。)

services.AddSingleton<IMongoClient>x => new
    MongoClient(My_Server_Connection1));

services.AddSingleton<IMongoClient>x => new
    MongoClient(My_Server_Connection2));

我希望能够在我的 DataStore 构造函数中执行类似的操作。

数据库数据存储1:

public DataStore1(IMongoClient clientWithConStr1, IMongoClient clientWithConStr2)
{
    database1 = clientWithConStr1.GetDatabase(DatabaseName1);
    database2 = clientWithConStr2.GetDatabase(DatabaseName1);
}
c# mongodb dependency-injection mongodb-.net-driver .net-8.0
2个回答
2
投票

对于要处理具有不同连接字符串的多个

MongoClient
的场景,最好实现一个工厂来按类型选择 MongoClient (提供者)。

  1. 接口和类提供程序,用于按类型启动和检索
    MongoClient
public interface IMongoClientProvider
{
    public int Type { get; }

    public IMongoClient GetMongoClient();
}

public class MongoClientProvider : IMongoClientProvider
{
    public int Type { get; init; }
    private readonly IMongoClient _client;

    public MongoClientProvider(int type, string connectionString)
    {
        Type = type;
        _client = new MongoClient(connectionString);
    }

    public IMongoClient GetMongoClient()
    {
        return _client;
    }
}
  1. 工厂按类型选择
    MongoClientProvider
    `。
using System.Collections.Generic;
using System.Linq;

public class MongoClientFactory
{
    private readonly IEnumerable<IMongoClientProvider> _providers;

    public MongoClientFactory(IEnumerable<IMongoClientProvider> providers)
    {
        _providers = providers;
    }

    public MongoClient GetMongoClient(int type)
    {
        var provider = _providers.SingleOrDefault(x => x.Type == type);
        if (provider == null)
        {
            throw new Exception("Unsupported type for provider.");
        }

        return provider.GetMongoClient();
    }
}
  1. MongoClientProvider
    MongoClientFactory
    注册到DI容器中。
services.AddSingleton<IMongoClientProvider>(new MongoClientProvider(1, My_Server_Connection));
services.AddSingleton<IMongoClientProvider>(new MongoClientProvider(2, My_Server_Connection2));

services.AddSingleton<MongoClientFactory>();
  1. DataStore
    类中,从 DI 获取
    MongoClientFactory
    并通过
    MongoClient
    检索
    type
    实例。
public class DataStore1
{
    private readonly IMongoDatabase database;
    private readonly string databaseName = "DatabaseName1";
    
    public DataStore1(MongoClientFactory factory)
    {
        var client = factory.GetMongoClient(1);
        database = client.GetDatabase(databaseName);
    }
}

public class DataStore2
{
    private readonly IMongoDatabase database;
    private readonly string databaseName = "DatabaseName2";
    
    public DataStore2(MongoClientFactory factory)
    {
        var client = factory.GetMongoClient(2);
        database = client.GetDatabase(databaseName);
    }
}

1
投票

您可以通过 密钥服务注册(随 .NET 8 发布的一项新功能)轻松实现此目的。

这允许您注册服务并提供密钥。您还可以指定要将实例注入到的位置的键。这样,您就不必创建标记接口,而只需依赖 .NET 依赖注入即可。

以下示例将两个

MongoClient
实例注册为单例,一个实例的键为 "MongoClientA",另一个实例的键为 "MongoClientB"。此示例仅设置不同的应用程序名称以表明实例已正确注入;在生产代码中,您可能会从配置中读取不同的连接字符串。

两个实例都被注入到

Datastore
实例中;使用
FromKeyedServices
属性允许 IoC 容器区分注册:

using Microsoft.Extensions.DependencyInjection;
using MongoDB.Driver;

var prov = new ServiceCollection()
    .AddKeyedSingleton<IMongoClient>(
    Constants.MongoClientA,
    (prov, key) =>
    {
        var settings = MongoClientSettings.FromConnectionString("mongodb://localhost:27017");
        settings.ApplicationName = "A";
        return new MongoClient(settings);
    })
    .AddKeyedSingleton<IMongoClient>(
    Constants.MongoClientB,
    (prov, key) =>
    {
        var settings = MongoClientSettings.FromConnectionString("mongodb://localhost:27017");
        settings.ApplicationName = "B";
        return new MongoClient(settings);
    })
    .AddSingleton<DataStore>()
    .BuildServiceProvider();

var ds = prov.GetRequiredService<DataStore>();

public class Constants
{
    public const string MongoClientA = "MongoClientA";
    public const string MongoClientB = "MongoClientB";
}

public class DataStore
{
    private readonly IMongoClient _clientA;
    private readonly IMongoClient _clientB;

    public DataStore(
        [FromKeyedServices(Constants.MongoClientA)] IMongoClient clientA, 
        [FromKeyedServices(Constants.MongoClientB)] IMongoClient clientB)
    {
        _clientA = clientA;
        _clientB = clientB;
        Console.WriteLine("ApplicationName A = " + clientA.Settings.ApplicationName);
        Console.WriteLine("ApplicationName B = " + clientB.Settings.ApplicationName);
    }
}

运行示例时,以下文本将写入控制台:

应用程序名称 A = A
应用程序名称 B = B

© www.soinside.com 2019 - 2024. All rights reserved.