2014-02-25 85 views
2

我想注入不同的字符串到我的每个模块的构造函数。我注册了构建模块的工厂方法。然后我可以打电话container.Resolve<T>(),一切都很好。出于某种原因,尽管当南希试图解决我的模块,它抛出的错误注册特定模块构造函数

Nancy.TinyIoc.TinyIoCResolutionException:无法解析类型: Plugin.HomeModule ---> Nancy.TinyIoc.TinyIoCResolutionException: 无法解析类型:System

public class HomeModule : NancyModule 
{ 
    public HomeModule(string text) 
    { 
    } 
} 

protected override void ConfigureApplicationContainer(TinyIoCContainer container) 
{ 
    base.ConfigureApplicationContainer(container); 
    container.Register<HomeModule>((ctr, param) => { return new HomeModule("text"); }); 
    HomeModule module = container.Resolve<HomeModule>(); 
} 

我自己也尝试做了登记ConfigureRequestContainer()具有相同的结果。我试过container.Register<HomeModule>(new HomeModule("some text"));以及AsSingleton()。我可以使用container.Register<string>("text")注册一个字符串类型的实现,但是这会将相同的字符串注入到所有模块中。

如何注册一个模块构造函数以便Nancy可以解决?

回答

3

模块通过INancyModuleCatalog,它通常由引导程序实现的获得,你必须创建一个自定义的变化 - 如果你正在使用默认的引导程序,那么这是当前实现:

https://github.com/NancyFx/Nancy/blob/master/src/Nancy/DefaultNancyBootstrapper.cs#L205

+0

由于'INancyModule GetModule(TinyIoCContainer容器,类型moduleType)'被密封意思的最佳方式为我写方法的自定义实现是从'NancyBootstrapperWithRequestContainerBase '直接导出? – Despertar

+1

只需创建您自己的目录实现并将其注册到ConfigureApplicationContainer中,我只是将该方法指向默认实现的一个示例,因为它稍微复杂一点,因为模块已在请求容器中注册,而不是主应用程序容器。 –

2

最好的方法是不要将原语传递给你的模块,但我们要更丰富一些,或者工厂。该容器可以解决这些依赖关系。将简单的字符串传递到模块是其他地方出现问题的迹象,并暗示您的架构可能需要重新思考

+1

容器也可以解析字符串类型。当我需要的时候传递一个产生我想要的值的工厂或者一个更丰富的类型时是一个字符串是差的设计IMO。借助依赖注入,课程应始终提出所需的内容。第二个也是更大的问题是IOC会将注入的类解析为相同的值(不管注册到哪个模块),所有模块都不允许将唯一值传递给作为问题核心的模块构造函数。 – Despertar

+1

我个人认为它的好设计,没有什么比使用需要随机字符串值的ctors项目工作更糟,这使得他们难以弄清楚他们为或做的任何事情。 – Phill

+0

@Phill上面写的代码只是一个任意的例子,构造函数可以带*任何*种类的值或类。我想展示一些简单的东西来展示我想要做的事情。我是依赖注入的忠实粉丝,我希望避免在任何可能的情况下进入全局状态以获取对象所需的值。出于这个原因,我正在研究如何以每个模块为基础自然地将数据传递给我的模块。由于Nancy与IOC容器强大集成,我认为注册模块工厂可以很容易地定制模块的构建方式。 – Despertar

0

我实现了仅注册特定命名空间的模块的自定义目录,但我不知道在哪里注册这个。

public CustomModuleCatalog() 
{ 
    // The license type is read from db in Global.ascx. 
    // So I want to register a module based on a namespace. 
    // The namespace is the same like the license name. 
    if(WebApiApplication.LicenseType == LicenseType.RouteOne) 
    { 
     var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes(); 
     var modules = assemblyTypes.Where(t => t.Namespace != null && t.Namespace.EndsWith("MyCustomNamespace")); 
     var nancy = modules.Where(t => t.IsAssignableFrom(typeof(INancyModule))); 
     foreach (var type in nancy) 
     { 
      var nancyType = (INancyModule)type; 
      _modules.Add(type, (INancyModule)Activator.CreateInstance(type)); 
     } 
    } 
} 

public IEnumerable<INancyModule> GetAllModules(NancyContext context) 
{ 
    return _modules?.Values; 
} 

public INancyModule GetModule(Type moduleType, NancyContext context) 
{ 
    if (_modules != null && _modules.ContainsKey(moduleType)) 
    { 
     return _modules[moduleType]; 
    } 
    return null; 
}