Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在插件式体系结构中使用Ninject_C#_.net_Plugins_Ninject - Fatal编程技术网

C# 在插件式体系结构中使用Ninject

C# 在插件式体系结构中使用Ninject,c#,.net,plugins,ninject,C#,.net,Plugins,Ninject,我正在学习DI,最近做了我的第一个项目 在这个项目中,我实现了存储库模式。我有接口和具体的实现。我想知道是否有可能将我的接口实现构建为“插件”,即我的程序将动态加载的DLL 因此,该程序可以随着时间的推移而改进,而不必重新构建它,您只需将dll放在“plugins”文件夹中,更改设置,然后瞧 这可能吗?Ninject能帮上忙吗?你可以用普通的C#反射轻松完成,你不需要任何额外的技术 网上有很多例子,例如。 通常,在主应用程序中,您需要加载实现插件的程序集,例如: ass = Assembly.

我正在学习DI,最近做了我的第一个项目

在这个项目中,我实现了存储库模式。我有接口和具体的实现。我想知道是否有可能将我的接口实现构建为“插件”,即我的程序将动态加载的DLL

因此,该程序可以随着时间的推移而改进,而不必重新构建它,您只需将dll放在“plugins”文件夹中,更改设置,然后瞧


这可能吗?Ninject能帮上忙吗?

你可以用普通的C#反射轻松完成,你不需要任何额外的技术

网上有很多例子,例如。

通常,在主应用程序中,您需要加载实现插件的程序集,例如:

ass = Assembly.Load(name);
然后你需要创建一个插件的实例。如果您知道类的名称,它将如下所示:

ObjType = ass.GetType(typename);
IPlugin plugin = (IPlugin)Activator.CreateInstance(ObjType);

然后您就可以使用它。

问题是,如果在模块加载中设置的对象在程序中使用,您可能需要重新编译。原因是您的程序可能没有类程序集的最新版本。例如,如果您为一个接口创建了一个新的具体类,那么假设您更改了插件dll。现在,Injector将加载它,但当它返回到您的程序(kernel.get(…)中时,您的程序可能没有程序集,并将抛出一个错误

我所说的例子如下:

BaseAuto auto = kernel.Get<BaseAuto>();//Get from the NInjector kernel your object. You get your concrete objet and the object "auto" will be filled up (interface inside him) with the kernel.

//Somewhere else:

public class BaseModule : StandardModule
{
        public override void Load(){
            Bind<BaseAuto>().ToSelf();
            Bind<IEngine>().To<FourCylinder>();//Bind the interface
        }     
 }
BaseAuto=kernel.Get()//从Ninject内核获取对象。您得到了具体的对象,对象“auto”将被内核填充(他内部的接口)。
//其他地方:
公共类BaseModule:StandardModule
{
公共覆盖无效负载(){
Bind().ToSelf();
Bind().To();//绑定接口
}     
}
如果您创建了一个名为SixCylinder的新的FourCylinder,您的实际程序将不会对新对象有任何引用。因此,一旦您从插件加载BaseModule.cs,您可能会在引用方面遇到一些问题。要做到这一点,您需要将这个具体实现的新dll与您的插件一起分发,该插件将包含注入器将接口加载到具体类所需的模块。这可以毫无问题地完成,但您开始有一个从插件加载的整个应用程序,在某些方面可能会有问题。注意


但是,如果您确实需要一些插件信息,您可以获得一些。

有多种方法可以实现这一点,您已经通过预定义的接口实现了实现这一点的主要目标。实际上,如果您的接口保持稳定,您应该能够构建核心应用程序

然而,我不确定Ninject的实现将如何工作。你们可以用反射或反射来实现这一点——尽管我认为反射是过分的,若你们并没有绝对的必要的话

使用提供程序模型方法,可以将文件放在/bin文件夹或正在探测的任何其他文件夹中,并调整.config文件以反映提供程序的存在。如果您有一个特定的“plugin”文件夹,您可以创建一个在应用程序启动时调用的方法,否则,可以定期扫描新的或删除的实例,并重新加载提供程序


这将在ASP.NET中,在C#或VB下工作。但是,如果您正在执行某种其他应用程序,则需要考虑另一种方法。该提供商实际上只是微软在这个问题上的宣传。

我对Activator.CreateInstance+Ninject很感兴趣,我只是想指出这方面的一些东西——希望它能激发一些人对这个问题提出一个真正的杀手级答案

如果您还没有遇到自动扫描模块和类并在Ninject中正确注册它们的麻烦,并且仍然通过Activator.CreateInstance创建插件,那么您可以在via中发布CreateInstance注入依赖项

IKernel k = ...
var o = Activator.CreateInstance(...);
k.Inject( o );

当然,这只是一个临时的解决方案,类似于

看看托管可扩展性框架

这个问题适用于我在这里提供的相同答案:

我很确定这就是你想要的:

var kernel = new StandardKernel();
kernel.Load( Assembly.Load("yourpath_to_assembly.dll");
如果查看Ninject.dll中带有reflector的KernelBase,您将看到此调用将递归加载加载的程序集中的所有模块(加载方法采用IEnumerable)

公共空心荷载(IEnumerable assemblies)
{
foreach(部件中的部件)
{
this.Load(assembly.GetNinjectModules());
}
}

我使用它的场景是,我不想直接引用程序集,因为它会经常更改,我可以交换程序集,为应用程序提供不同的模型(假设我有适当的测试)

我认为没有必要使用框架。本教程解决了您的问题

在您控制插件的情况下有效,但在插件可能由第三方开发并且您不希望它们必须依赖于编写ninject模块的情况下不起作用

这对于Ninject来说非常容易:

public static IKernel CreateKernel()
{
    var kernel = new StandardKernel();

    kernel.Scan(scanner => {
        scanner.FromAssembliesInPath(@"Path\To\Plugins");
        scanner.AutoLoadModules();
        scanner.WhereTypeInheritsFrom<IPlugin>();
        scanner.BindWith<PluginBindingGenerator<IPlugin>>();
    });

    return kernel;
}

private class PluginBindingGenerator<TPluginInterface> : IBindingGenerator
{
    private readonly Type pluginInterfaceType = typeof (TPluginInterface);

    public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
    {
        if(!pluginInterfaceType.IsAssignableFrom(type))
            return;
        if (type.IsAbstract || type.IsInterface)
            return;
        kernel.Bind(pluginInterfaceType).To(type);
    }
}
publicstaticikernelcreatekernel()
{
var kernel=新的标准内核();
kernel.Scan(scanner=>{
scanner.fromsassembliesinpath(@“Path\To\Plugins”);
scanner.AutoLoadModules();
scanner.WhereTypeInheritsFrom();
scanner.BindWith();
});
返回内核;
}
私有类插件绑定生成器:IBindingGenerator
{
私有只读类型pluginInterfaceType=typeof(TPluginInterface);
public void进程(类型、Func scopeCallback、IKernel内核)
{
如果(!pluginInterfaceType.IsAssignableFrom(类型))
返回;
if(type.IsAbstract | | type.IsInterface)
public static IKernel CreateKernel()
{
    var kernel = new StandardKernel();

    kernel.Scan(scanner => {
        scanner.FromAssembliesInPath(@"Path\To\Plugins");
        scanner.AutoLoadModules();
        scanner.WhereTypeInheritsFrom<IPlugin>();
        scanner.BindWith<PluginBindingGenerator<IPlugin>>();
    });

    return kernel;
}

private class PluginBindingGenerator<TPluginInterface> : IBindingGenerator
{
    private readonly Type pluginInterfaceType = typeof (TPluginInterface);

    public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
    {
        if(!pluginInterfaceType.IsAssignableFrom(type))
            return;
        if (type.IsAbstract || type.IsInterface)
            return;
        kernel.Bind(pluginInterfaceType).To(type);
    }
}
var kernel = new StandardKernel();
kernel.Bind(scanner => scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
                                   .SelectAllClasses()
                                   .InheritedFrom<IPlugin>()
                                   .BindToAllInterfaces());