C # Обтекание и инициализация нескольких в интерфейс - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть контроллер API, как показано ниже:

 public class ValuesController : Controller
 {
     private static string dynamoDbTable = string.Empty;        
     private IDynamoDbClientInitialization _clientAccessor;

    public ValuesController(IOptions<Dictionary<string, string>> appSettings, IDynamoDbClientInitialization clientAccessor)
    {
        var vals = appSettings.Value;            
        dynamoDbTable = vals["dynamoDbTable"];                   
        _clientAccessor = clientAccessor;
    }

    [HttpGet("data")]
    public async Task<List<MyData>> GetData()
    {      
        List<ScanCondition> conditions = new List<ScanCondition>();
        var response = await _clientAccessor.GetContext().ScanAsync<MyData>(conditions, AWSHelperMethods.GetDynamoDbOperationConfig(dynamoDbTable)).GetRemainingAsync();
        return response.ToList();
    }  
}   

Также у меня есть класс помощника:

public static class AWSHelperMethods
{        
    public static BasicAWSCredentials SetAwsCredentials(string awsId, string awsPassword)
    {
        var creds = new BasicAWSCredentials(awsId, awsPassword);
        return creds;
    }

    public static AmazonDynamoDBClient GetDynamoDbClient(BasicAWSCredentials creds, RegionEndpoint awsDynamoDbRegion)
    {
        var client = new AmazonDynamoDBClient(creds, awsDynamoDbRegion);
        return client;
    }

    public static DynamoDBContext GetDynamoDbContext(AmazonDynamoDBClient client)
    {
        var context = new DynamoDBContext(client);
        return context;
    }

    public static DynamoDBOperationConfig GetDynamoDbOperationConfig(string dynamoDbTable)
    {
        DynamoDBOperationConfig config = new DynamoDBOperationConfig() { OverrideTableName = dynamoDbTable };
          return config;
    }   
}

Моя IDynamoDbClientInitialization имеет вид:

public interface IDynamoDbClientInitialization
{
    DynamoDBContext GetContext();
}


public class DynamoDbClientInitialization : IDynamoDbClientInitialization
{
    private readonly DynamoDbClientSettings settings;
    private DynamoDBContext _awsContext;

    public DynamoDbClientInitialization(IOptions<DynamoDbClientSettings> options)
    {
        settings = options?.Value;
    }

    public DynamoDBContext GetContext()
    {         
        //Check is context already exists. If not create a new one.
        if(_awsContext != null)
        {
            return _awsContext;
        }
        else
        {                
            var creds = AWSHelperMethods.SetAwsCredentials(settings.Id, settings.Password);
            var dynamoClient = AWSHelperMethods.GetDynamoDbClient(creds, settings.Region);
            _awsContext = AWSHelperMethods.GetDynamoDbContext(dynamoClient);

            return _awsContext;
        }

    }
}

И, наконец, мой стартап выглядит так:

public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<IDynamoDbClientInitialization, DynamoDbClientInitialization>();
    services.Configure<DynamoDbClientSettings>(c =>
    {
        c.Id = Configuration.GetValue<string>("AppSettings:awsId");
        c.Password = Configuration.GetValue<string>("AppSettings:awsPassword"); 
        c.Region = RegionEndpoint.GetBySystemName(Configuration.GetValue<string>("AppSettings:dynamoDbRegion")); 
    });     
}

Теперь я создал приведенный выше код без учета интерфейсов. Теперь мне нужно написать тестовые примеры для этого, поэтому хотел знать, как я могу создать один класс и обернуть все вышеперечисленное код вместо создания нескольких классов, таких как DynamoDbClientInitialization и вспомогательный класс. Чтобы вместо инициализации каждого класса я просто инициализировал один класс, скажем «DbManager», который обрабатывает все вышеописанное.

1 Ответ

0 голосов
/ 06 ноября 2018

Вы можете использовать контейнер IoC. (См. сравнение здесь ). Контейнеры IoC могут автоматически разрешать необходимые службы. Предположим, что у нас есть интерфейсы IA, IB, IC и классы A, B, C, реализующие их:

public class A : IA
{
    ...
}

public class B : IB
{
    private readonly IA _a;

    public B(IA a)
    {
        _a = a;
    }

    ...
}

public class C : IC
{
    private readonly IB _b;

    public C(IB b)
    {
        _b = b;
    }

    ...
}

Затем вы инициализируете контейнер с помощью (детали отличаются в разных реализациях, но это дает вам представление):

public static ISomeContainer Container { get; } = container = new SomeContainer();

...

container.Register<IA, A>();
container.Register<IB, B>();
container.Register<IC, C>();

Вы также можете указать, что вы хотите, чтобы сервисы создавались как одиночные. Э.Г.

container.Register<IB, B>().AsSingleton();

Теперь вы можете получить услугу с

var myC = container.Resolve<IC>();

Теперь контейнер автоматически создает объект A, затем создает объект B, используя первый объект в качестве аргумента конструктора. Наконец, он создает и возвращает объект C, используя объект B в качестве аргумента конструктора.

Это означает, что у вас могут быть разные классы, реализующие один и тот же интерфейс, но имеющие разные типы и числа параметров конструктора, и IoC автоматически разрешает все эти параметры.

Вы также можете зарегистрировать разные классы для одного и того же интерфейса, используя ключ, который вы можете указать при разрешении службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...