C# 根据需要使用简单喷油器加载组件

C# 根据需要使用简单喷油器加载组件,c#,.net,wpf,dependency-injection,simple-injector,C#,.net,Wpf,Dependency Injection,Simple Injector,这个问题目前是关于SimpleInjector的,但是可以应用于任何可以更好地处理这个问题的DI容器 我现在正在为我的公司做研究。我觉得DI容器可以让事情变得更简单,但是它的力量有一些问题,所以我开始尝试解决其中的一些问题,以证明DI容器的价值。我们有一个非常大的ERP系统,我们即将开始我们旗舰产品的下一次迭代。该产品将包含多个大型组件,可能至少20-30个,所有这些组件都是大型的 可以说,用户的主要访问点是一个shell,它由一个程序集组成,当用户在应用程序中导航时,将调用其他程序集。我们不想

这个问题目前是关于SimpleInjector的,但是可以应用于任何可以更好地处理这个问题的DI容器

我现在正在为我的公司做研究。我觉得DI容器可以让事情变得更简单,但是它的力量有一些问题,所以我开始尝试解决其中的一些问题,以证明DI容器的价值。我们有一个非常大的ERP系统,我们即将开始我们旗舰产品的下一次迭代。该产品将包含多个大型组件,可能至少20-30个,所有这些组件都是大型的

可以说,用户的主要访问点是一个shell,它由一个程序集组成,当用户在应用程序中导航时,将调用其他程序集。我们不想耽误启动时间,所以我们想找到一种根据需要加载程序集的方法。只有当需要某个特定程序集的某些内容时,才应该加载该程序集,直到那时它才应该位于内存中


有没有办法用简单的注入器或DI容器来实现这一点?我们正在用WPF编写我们的应用程序。

您的需求有点棘手,因为DI容器的正常使用情况是预先加载所有内容。这样做更简单,因为您只需通过为每个根类型(或根类型组)提供自己的方法来延迟程序集加载。程序集加载发生在从程序集中引用类型的方法被JIT时

因此,对于纯DI,我将合成根想象成这样:

public static object GetRootType(Type type) {
    if (type == typeof(HomeController))
        return GetHomeController();
    if (type == typeof(ShipOrderController))
        return GetShipOrderController();
    if (type == typeof(CancelOrderController))
        return GetCancelOrderController();
    // etc
}

private static object GetCancelOrderController() {
    return new CancelOrderController(
        ApplyAop(new CancelOrderHandler(new UnitOfWork())));
}

private static object GetShipOrderController() { ... }
private static object GetHomeController() { ... }
private static ICommandHandler<T> ApplyAop<T>(ICommandHandler<T> handler) {
    return new TransactionCommandHandlerDecorator<T>(
        new ValidationCommandHandlerDecorator<T>(handler));
}
对于第二种方法,您将以相同的方式使用
resolveUnregistedType
事件,但允许在最后一分钟在同一容器中注册所有注册

最后一点。当然,我看不出您正在构建什么样的“flag ship”应用程序。对于我在运营商中看到的大多数应用程序,这种延迟的程序集加载没有多大意义。它通常只适用于真正大型的两层应用程序。两层应用程序是直接与数据库对话的厚客户端(Win窗体、WPF等)应用程序。如今,这种两层应用程序非常少见,因为在大多数情况下,添加第三层(位于客户机和数据库之间的web服务)要好得多。更好是因为您可以添加添加的安全层,更好是因为您可以在该级别上拥有额外的控制(日志记录、调优、审计跟踪)。在web服务层,实现延迟程序集加载通常没有什么好处,因为web应用程序可以预加载,比预加载厚客户端应用程序容易得多


当然,这并不适用于所有类型的应用程序。例如,如果您正在构建类似VisualStudio的东西(它使用托管可扩展性框架来延迟程序集加载btw),那么添加第三层通常是一种非常好的方法。当您围绕诸如和之类的模式构建应用程序时,第三层的开销非常小。

我认为您可以使用Castle Windsor实现您的要求。pluralsight上有一段关于AOP的视频,我很确定他使用CW加载程序集。我在这里也发现了一个帖子,不确定它是否会有帮助:嗯,很有趣。唯一的问题是,如果可以的话,我也应该避免使用XML配置,但我想这是第二个问题。不过,谢谢你提供的信息@DanielHakimi:在Stackoverflow上引用Pluralsight视频并没有什么帮助。我不认为这段视频实际上进入了延迟的程序集加载;通常的做法是在启动时反映和加载所有程序集,并在启动时在容器中进行所有注册。这是OP不想要的行为,因为应用程序启动限制。非常详细的回答,谢谢。我自己更喜欢三层或更解耦的应用程序体系结构,但它可能不是我们最终要做的。不过,这也值得思考,我真的很感谢这些反馈和链接。
var asm1Container = new lazy<Container>(Asm1Bootstrapper.Bootstrap);
var asm2Container = new lazy<Container>(Asm2Bootstrapper.Bootstrap);
var asm3Container = new lazy<Container>(Asm3Bootstrapper.Bootstrap);

mainContainer.ResolveUnregisteredType += (s, e) =>
{
    var asmContainer = GetAssemblyContainer(e.UnregisteredServiceType.Assembly);
    e.Register(() => asmContainer.GetInstance(e.UnregisteredServiceType));
}

private Container GetAssemblyContainer(Assembly assembly) {
    string assemblyName = assembly.FullName;
    if (assemblyName.Contains("Assembly1"))
        asm1Container.Value;
    if (assemblyName.Contains("Assembly2"))
        asm2Container.Value;
    if (assemblyName.Contains("Assembly3"))
        asm3Container.Value;
    // etc
}