C# 内置的Ninject程序集加载程序是否有错误处理

C# 内置的Ninject程序集加载程序是否有错误处理,c#,plugins,dependency-injection,ninject,C#,Plugins,Dependency Injection,Ninject,我写了一个插件管理器 public class WeinCadPluginManager : NinjectModule, IEnableSerilog { public override void Load() { var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase); var codeBasePath = Uri.UnescapeDataString(codeB

我写了一个插件管理器

public class WeinCadPluginManager : NinjectModule, IEnableSerilog
{
    public override void Load()
    {

        var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
        var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
        var dirPath = Path.GetDirectoryName(codeBasePath);
        Debug.Assert(dirPath != null, "dirPath != null");
        var path = dirPath;

        var types = Directory
            .GetFiles(path, "*.dll")
            .Select (Assembly.LoadFile)
            .SelectMany (assembly =>
                {
                    try
                    {
                        return assembly.GetExportedTypes();
                    }
                    catch (Exception e)
                    {
                        this.Serilog()
                            .Error
                            (e, "Failed to load assembly {assembly}", assembly);
                        return new Type[]
                        {
                        };
                    }
                })
            .Where(type=>typeof(IWeinCadPlugin).IsAssignableFrom(type))
            .ToList();

        foreach (var assembly in types)
        {
            Kernel.Bind<IWeinCadPlugin>().To(assembly).InSingletonScope();
        }
    }
}

除非从程序集导出类型时出现任何错误,否则
Kernel.Load
将崩溃,无法进行错误处理。我不希望加载单个插件程序集的失败导致我的应用程序崩溃。我的解决方案是唯一可行的方法,还是Ninject有一些可用的错误处理方法?

我认为在每个
内核周围使用
尝试{}catch{}
。Load(“specificplugin.dll”)
就足够了。 您仍然需要自己查找所有程序集,但必须编写更少的代码

var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
var dirPath = Path.GetDirectoryName(codeBasePath);

var dllPaths = Directory.GetFiles(dirpath, "*.dll");

foreach(string dllPath in dllPaths)
{
     try
     {
         kernel.Load(dllPath);
     }
     catch (Exception e)
     {
         this.Serilog()
             .Error(e, "Failed to load assembly {assembly}", assembly);
     }
}
缺点:ninject必须在
.Bind()
.to(..)
上向内核添加绑定,因为所有其他fluent语法方法都是可选的。因此,如果在
.When()
.InScope()
,。。任何其他可选方法,都会留下一个不完整的绑定,因此很可能是一个错误的软件

(但是,我怀疑大多数错误不会在创建绑定时出现,而是在激活绑定时出现。您没有受到保护。)

据我所知,一旦添加了绑定,就无法从ninject中删除它们。除了
.Rebind()
——但这总是用不同的绑定替换绑定。 所以不,我不认为有什么像“在异常时回滚”

因此,我们必须寻找另一种解决办法。有一个:子内核

将每个插件加载到它自己的子内核中。如果fooplugin.dll加载失败,请处置子内核。以防万一。。好吧,你可以走了!:) 这也有一个优点,即插件之间不能相互影响。设想两个插件可以执行
IBindingRoot.Bind().ToConstant(“某个常量”)
;-)

(请注意,我还没有测试在父内核“按预期”工作之前是否处理子内核,所以您应该首先测试它。足够简单,对吗?)

var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
var dirPath = Path.GetDirectoryName(codeBasePath);

var dllPaths = Directory.GetFiles(dirpath, "*.dll");

foreach(string dllPath in dllPaths)
{
     try
     {
         kernel.Load(dllPath);
     }
     catch (Exception e)
     {
         this.Serilog()
             .Error(e, "Failed to load assembly {assembly}", assembly);
     }
}