Как лучше всего настроить StackExchange.Redis с помощью Autofac?

В документации StackExchange.Redis рекомендуется только создайте его и повторно используйте подключение к Redis.

В передовых практиках Azure Redis рекомендуется использовать следующий шаблон:

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    return ConnectionMultiplexer.Connect("cachename.redis.cache.windows.net,ssl=true,abortConnect=false,password=password");
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}

но как мне заставить это работать с Autofac, где я хочу, чтобы конфигурация была установлена ​​в файлах конфигурации веб / приложения?

В настоящее время у меня есть RedisCacheProvider:

private readonly ConnectionMultiplexer _connection;

public RedisCacheProvider(string config)
{
    _connection = ConnectionMultiplexer.Connect(config);
}

и в моей конфигурации Autofac:

builder.RegisterType<RedisCacheProvider>().As<ICacheProvider>().WithParameter("config", "localhost");

Я думаю, я должен изменить свой RedisCacheProvider, чтобы он принимал ConnectionMultiplexer, который передается через статическую переменную?

Обновление: мое решение на данный момент:

Мой RedisCacheProvider (введение интерфейса позволяет мне имитировать соединение в модульных тестах):

private readonly IConnectionMultiplexer _connection;

public RedisCacheProvider(IConnectionMultiplexer connection)
{
   _connection = connection;
}

Класс RedisConnection для хранения статического свойства и чтения конфигурации из файла конфигурации:

public class RedisConnection
{
    private static readonly Lazy<ConnectionMultiplexer> LazyConnection = 
        new Lazy<ConnectionMultiplexer>(
            () => ConnectionMultiplexer.Connect(ConfigurationManager.AppSettings["RedisCache"]));

    public static ConnectionMultiplexer Connection
    {
        get
        {
            return LazyConnection.Value;
        }
    }
}

Регистрация в модуле Autofac:

builder.RegisterType<RedisCacheProvider>().As<ICacheProvider>()
                    .WithParameter(new TypedParameter(
                                       typeof(IConnectionMultiplexer), 
                                       RedisConnection.Connection));

person EdmundYeung99    schedule 16.07.2015    source источник
comment
Из того, что вы написали, я предлагаю вам взглянуть на фабрики делегатов Autofac.   -  person Alexey Zimarev    schedule 19.07.2015


Ответы (1)


Autofac поддерживает неявные типы отношений, а ленивое ‹› вычисление поддерживается «из коробки». Итак, после того, как вы зарегистрируете свой RedisCacheProvider, как в вашем примере, это

builder
.RegisterType<RedisCacheProvider>()
.As<ICacheProvider>()
.WithParameter("config", "localhost");

вы можете решить эту проблему, как показано ниже:

container.Resolve<Lazy<ICacheProvider>>();

Но не забывайте, что область действия Autofac по умолчанию - InstancePerDependency (временная). То есть вы будете получать новый экземпляр RedisCacheProvider каждый раз при его разрешении или всякий раз, когда он предоставляется другому компоненту в качестве зависимости. Чтобы исправить это, вам необходимо явно указать область его существования. Например, чтобы сделать его одноэлементным, вам нужно изменить регистрацию, как показано ниже:

builder
.RegisterType<RedisCacheProvider>()
.As<ICacheProvider>()
.WithParameter("config", "localhost")
.SingleInstance();

Другое предположение заключается в том, что RedisCacheProvider - единственный компонент, в котором используется соединение Redis. Если это не так, вам лучше позволить Autofac управлять областью жизни соединения Redis (что в любом случае лучше) и получить соединение как зависимость в RedisCacheProvider. То есть:

public RedisCacheProvider(IConnectionMultiplexer connection)
{
    this.connection = connection;
}

....

builder
.Register(cx => ConnectionMultiplexer.Connect("localhost"))
.As<IConnectionMultiplexer>()
.SingleInstance();

builder
.RegisterType<RedisCacheProvider>()
.As<ICacheProvider>();
person Vitaliy Tsvayer    schedule 19.07.2015
comment
Я не об этом прошу, я спрашиваю, как я могу использовать статическое свойство с моим RedisCacheProvider. Вы предоставили мне альтернативный способ регистрации одного экземпляра объекта Redis Connection. - person EdmundYeung99; 19.07.2015
comment
С помощью обновленного кода вы пытаетесь вручную управлять жизненным циклом компонентов: синглтон, ленивая оценка. Это именно то, для чего используется контейнер внедрения зависимостей, в вашем случае Autofac. - person Vitaliy Tsvayer; 20.07.2015
comment
Согласие на то, чтобы позволить контейнеру обрабатывать срок службы соединения, является лучшим подходом. Как бы лениво установить соединение? Будет ли что-то вроде этого работать с этой регистрацией: RedisCacheProvider (Ленивое соединение ‹IConnectionMultiplexer›)? Или это необходимо для builder.Register (cx = ›new Lazy ‹ConnectionMultiplexer› (ConnectionMultiplexer.Connect (localhost))); ? - person Tom; 11.04.2016