当前位置: 首页 > 编程语言 > C#

在像体系结构这样的插件中使用Ninject分享

时间:2023-04-11 10:44:06 C#

C#学习教程:在Architecture之类的插件中使用Ninject在这个项目中,我实现了存储库模式。我有接口和具体实现。我想知道是否有可能将我的接口的实现构建为一个“插件”,一个我的程序将动态加载的dll。所以程序可以随着时间的推移而增长而无需重建它,您只需将dll放在“插件”文件夹中,更改设置即可!是否可以?Ninject可以帮助解决这个问题吗?虽然SeanChambers的解决方案适用于您控制插件的情况,但如果插件可能由第三方开发并且您不希望它们必须依赖于编写ninject模块,则它不起作用。对于Ninject的合约扩展,这很容易做到:publicstaticIKernelCreateKernel(){varkernel=newStandardKernel();kernel.Scan(scanner=>{scanner.FromAssembliesInPath(@"PathToPlugins");scanner.AutoLoadModules();scanner.WhereTypeInheritsFrom();scanner.BindWith>();});返回内核;}privateclassPluginBindingGenerator:IBindingGenerator{privatereadonlyTypepluginInterfaceType=typeof(TPluginInterface);publicvoidProcess(Typetype,Funcscopekernelback,IKernel){if(!pluginInterfaceType.IsAssignableFrom(type))返回;如果(类型。IsAbstract||类型。IsInterface)返回;kernel.Bind(pluginInterfaceType).To(类型);然后你可以使用kernel.GetAll()获取所有加载的插件。这种方法的优点是:您的插件dll不需要知道它们正在被ninject加载,因为具体的插件实例将由ninject解析,因此它们可以使用构造函数来注入插件主机知道如何构造的类型.这个问题适用于我在这里提供的相同答案:CanNInjectloadmodules/componentsondemand?我很确定这就是您要找的:varkernel=newStandardKernel();kernel.Load(Assembly.Load("yourpath_to_assembly.dll");如果你在Ninject.dll中用反射器查看KernelBase,你会看到这个调用将递归地加载已加载程序集中的所有模块(Load方法需要一个IEnumerable)publicvoidLoad(IEnumerableassemblies){foreach(Assemblyassemblyinassemblies){this.Load(assembly.GetNin??jectModules());}}我正在使用这种情况,我不希望直接的程序集引用经常改变,我可以换掉程序集,为应用程序提供不同的模型(允许我进行适当的测试)扩展@ungood的好答案,基于v.2,使用Ninjectv.3(目前在RC3上),它可以变得更容易.您不再需要任何IPluginGenerator,只需编写:varkernel=newStandardKernel();kernel.Bind(scanner=>scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).SelectAllClasses()。InheritedFrom().BindToAllInterfaces());请注意,我正在寻找在应用程序中以与您的程序相同的路径实现IPlugin(将您的接口放在这里)的插件。您可以使用普通的C#反射轻松完成,您不需要任何额外的技术。网上有很多例子,比如http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx通常在主应用中,需要加载实现插件的程序集,eg:ass=Assembly。加载(名称);然后你需要创建一个插件实例。如果您知道类的名称,它将如下所示:ObjType=ass.GetType(typename);IPlugin插件=(IPlugin)Activator.CreateInstance(ObjType);然后你就可以使用它了。查看托管可扩展性框架。http://www.codeplex.com/MEF有多种方法可以解决这个问题,您已经完成了通过预定义接口实现具体实现的主要目标。事实上,如果您的界面保持稳定,您应该能够构建核心应用程序。但是,我不确定该实现如何与Ninject一起使用。您可以使用提供者模型或反射来做到这一点——尽管我认为如果您不是绝对需要这样做,反射就太过分了。使用提供者模型方法,将文件放在/bin文件夹或您正在探测的任何其他文件夹中,并调整.config文件以反映提供者的存在。如果你有一个特定的“插件”文件夹,你可以创建在应用程序启动时调用的方法,并定期扫描新的或删除的实例并重新加载提供程序。这可以在ASP.NET、C#或VB下使用。但是,如果您正在做一些其他应用程序,则可以考虑另一种方法。提供商实际上只是微软战略范式的转变。我将此作为Activator.CreateInstance+Ninject的热门话题,只是想指出这方面的一些东西-希望它会激发某人对SO上的这个问题提出真正的杀手级答案。如果您还没有经历自动扫描模块和类并正确注册Ninject的麻烦,并且仍在通过Activator.CreateInstance创建插件,您可以在CreateInstance后注入依赖项IKernelk=...varo=Activator.CreateInstance(...);k.注入(o);当然,这只是像http://groups.google.com/group/ninject/browse_thread/thread/880ae2d14660b33c这样的临时解决方案。我认为不需要框架。本教程解决了您的问题http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx问题是,如果您在程序中使用模块加载中设置的对象,则可能需要重新编译。原因是你的程序可能没有最新版本的程序集。例如,如果您为其中一个接口创建一个新的具体类,假设您更改了插件dll。现在,Injector将加载它,很好,但是当它返回到您的程序(kernel.get(...))时,您的程序可能没有程序集并会抛出错误。我正在谈论的示例:BaseAutoauto=kernel.Get();//从NInjector内核获取您的对象。你得到你的具体对象,对象“auto”将被内核填充(他内部的接口)。//其他地方:publicclassBaseModule:StandardModule{publicoverridevoidLoad(){Bind().ToSelf();Bind().To();//绑定接口}}如果你创建一个名为newFourCylinder的SixCylinder,那么你的真实程序将不会引用你的新对象。因此,一旦您从PlugInBaseModule.cs加载,您可能会遇到一些参考问题。为了能够做到这一点,您需要使用您的插件分发这个具体实现的新dll,该插件将具有注入器将接口加载到具体类所需的模块。这可以毫无问题地完成,但是当您从插件加载时,您开始拥有一个完整的应用程序,这在某种程度上可能是有问题的。实现了。但是,如果您确实需要一些插件信息,可以从CodeProject获得一些教程。以上就是C#学习教程:在架构类插件中使用Ninject分享的所有内容,如果对你有用,需要进一步了解C#学习教程,希望大家多多关注——本文来自网络收藏,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢