Внедрение конкретной реализации WCF ServiceContract на основе значения off в файле конфигурации димамно

Скажем, у меня есть следующий контракт на обслуживание и две конкретные реализации:

[OperationContract]
public interface ISearchService {
    public ICollection<string> Search(string text);
}

[SearchServiceBehaviour]
public class SolrSearchService : ISearchService {
    public ICollection<string> Search(string text) {
        // Implementation...
    }
}

[SearchServiceBehaviour]
public class SqlSearchService : ISearchService {
    public ICollection<string> Search(string text) {
        // Implementation...
    }
}

Это связано с ServiceBehavior так что я могу создать экземпляр, пока служба работает на основе файла конфигурации:

public class SearchServiceBehaviour : Attribute, IServiceBehavior {
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
        foreach (var item in serviceHostBase.ChannelDispatchers) {
            var dispatcher = item as ChannelDispatcher;

            if (dispatcher != null) {
                dispatcher.Endpoints.ToList().ForEach(e => {
                    e.DispatchRuntime.InstanceProvider = new SearchServiceInstanceProvider();
                });
            }
        }
    }
}

public class SearchServiceInstanceProvider : IInstanceProvider {
    public object GetInstance(InstanceContext instanceContext, Message message) {
        // Should cache and only do this at an interval.
        ConfigurationManager.RefreshSection("appSettings");
        var index = ConfigurationManager.AppSettings["UseSolr"] as string;

        bool UseSolr;
        bool.TryParse(index, out UseSolr);

        if (UseSolr)
            return new IndexedSearchService();
        else
            return new SearchService();
    }
}

Мой вопрос: как я могу внедрить конкретную реализацию, используя Ninject, основываясь на изменяющемся значении в файле конфигурации? Кажется, я должен сделать следующее:

public class SearchServiceModule : NinjectModule {
    private bool UseSolr;

    public SearchServiceModule() {
        // Should cache and only do this at an interval.
        ConfigurationManager.RefreshSection("appSettings");
        var index = ConfigurationManager.AppSettings["UseSolr"] as string;

        bool.TryParse(index, out UseSolr);
    }

    public override Load() {
        if (UseSolr)
            Bind<ISearchService>().To<SolrSearchService>();
        else 
            Bind<ISearchService>().To<SqlSearchService>();
    }
}

А потом в InstanceProvider:

public object GetInstance(InstanceContext instanceContext, Message message) {
    return _kernel.Get<ISearchService>();
}

Однако привязки в Ninject не меняются после того, как я изменяю значение в файле конфигурации. Есть ли способ изменить привязку на основе значения в файле конфигурации? Я что-то здесь не так делаю?

2 ответа

Решение

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

Также взгляните на условные привязки. .Когда()

Вы самостоятельно размещаетесь в службе Windows. Сохранение файла.config не приводит к автоматической перезапуску службы Windows и обнаружению изменения.config (в отличие от IIS). Так что, если вы собираете ядро ​​при запуске, нет триггера, который заставил бы его перестраиваться.

Вам придется изменить свою реализацию, чтобы использовать .When() метод для обеспечения реализации на основе параметров конфигурации. Это будет выглядеть примерно так:

public override Load() 
{ 
    Bind<ISearchService>().To<SolrSearchService>().When(r => ShouldUseSolr());
    Bind<ISearchService>().To<SqlSearchService>().When(r => !ShouldUseSolr());
}

private static ShouldUseSolr()
{
    // Should cache and only do this at an interval.  
    ConfigurationManager.RefreshSection("appSettings");  
    var index = ConfigurationManager.AppSettings["UseSolr"] as string;  

    bool result;

    bool.TryParse(index, out result);  

    return result;
}
Другие вопросы по тегам