Search code examples
c#.netwcfninjectninject-3

Injecting a concrete implementation of a WCF ServiceContract based off value in a config file dymamically


Say I have the following service contract and two concrete implementations:

[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...
    }
}

These are attributed with a ServiceBehavior so that I can create the instance whilst the service is running based off a config file:

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();
    }
}

My question is how can I inject the concrete implementation using Ninject based off a changing value in a config file? It seems to be I should be doing the following:

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>();
    }
}

And then in the InstanceProvider:

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

However, the bindings in Ninject don't change after I change the value in the config file. Is there a way to change the binding based off the value in the config file? Am I doing something wrong here?


Solution

  • Your module does not behave as you expect because there is a field and a local variable with the same name.

    Also have a look at conditional bindings. .When()