在配置文件中以动态方式注入基于WCF ServiceContract的具体实现

时间:2012-04-11 23:36:57

标签: c# .net wcf ninject ninject-3

说我有以下服务合同和两个具体实施:

[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 个答案:

答案 0 :(得分:4)

您的模块的行为与预期不符,因为有一个字段和一个同名的局部变量。

另请参阅条件绑定。 。当()

答案 1 :(得分:1)

您在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;
}