【问题标题】:Constructor injected implementation has a dll dependency which is not used构造函数注入实现具有未使用的 dll 依赖项
【发布时间】:2018-05-30 11:35:06
【问题描述】:

如您所知,Ninject 将所有接口绑定到组合根中的实现。我们有一个依赖于外部 dll 的类,但如果它没有被使用,我们不想部署它(bin 目录中的物理 dll 文件)。 ExampleClass 类存储在我们的框架项目中,这意味着它被我们正在构建的任何应用程序引用。这就是为什么我们在部署任何应用程序时都会得到以下结果:

无法加载文件或程序集 ExternalDll,版本=x.x.x.xxx, 文化=中立,PublicKeyToken=xxxxxxxxxxxxxxxxx

是否有任何解决方法,例如将实现封装到另一个类或其他东西中?或运行时初始化(工厂模式)。其中哪一个可以解决我的问题?我也尝试过惰性绑定,但没有成功。

使用外部 dll 的实现的构造函数注入

namespace Framework
{
    public class ExampleClass
    {
        private readonly IUsesExternalDll _usesExternalDll;

        public ExampleClass(IUsesExternalDll usesExternalDll)
        {
            _usesExternalDll = usesExternalDll;
        }
    }
}

界面

public interface IUsesExternalDll
{

}

实施

using externalDll; //this using is a reference to external dll

public class UsesExternalDll : IUsesExternalDll
{

}

绑定

kernel.Bind<IUsesExternalDll>().To<UsesExternalDll>().InTransientScope();

【问题讨论】:

  • 也许我没有明白这一点,但IUsesExternalDllUsesExternalDll 在同一个程序集中吗?如果是这样,您可以将接口分离到一个公共程序集中。接口程序集始终需要与您的所有应用程序一起部署,但您应该能够省略带有具体类 UsesExternalDll 的程序集,当然前提是您不尝试引导它。
  • 本例中的接口和实现在同一个程序集中。引导它是什么意思?如果我删除 Ninject Binding,它说它无法解决。如果添加了绑定,它还需要 .dll 文件......而对于程序集,您的意思是项目程序集,而不是命名空间,对吗?
  • @StuartLC 一分钟前我读过的很棒的文章:blinkingcaret.com/2016/02/03/…。不幸的是,我们的软件没有被组装分开。我知道这是糟糕的设计......但是没有解决我上述问题的快速解决方案吗?但是仍然有一个地方我将接口绑定到实现,并且正在初始化实现,它将寻找 dll。所以这意味着,dll 必须始终存在?
  • 我刚刚构建了一个示例,不,ExternalDll 将始终被拖到最终的应用程序中,即使ExternalDll 中的任何类/方法都没有被它实际使用(如果您将接口分成IExternalDll 并仅通过接口耦合Framework,那很好)。如果ExternalDll 包含敏感代码,您可以尝试创建一个欺骗性的 dll(前提是它没有 strong name),这应该可以安抚 Fusion。但我认为从长远来看,您可能正在寻找一种“插件”模式的方法来管理 DLL。

标签: c# .net dependency-injection inversion-of-control ninject


【解决方案1】:

您可以将您的绑定替换为约定绑定:

kernel.Bind(x => x.FromAssembliesMatching("AssemblyWhereUsesExternalDllIsLocated.dll")
    .SelectAllClasses()
    .BindAllInterfaces()
    .Configure(c => c.InTransientScope()));

现在只有在找到这个程序集时才绑定里面的类型。

【讨论】:

  • 我怎样才能只绑定 IUsesExternalDll 而不是全部?顺便说一句,AssemblyWhereUsesExternalDllIsLocated.dll 将永远存在。所以我认为这不是我的问题的解决方案。
【解决方案2】:

我是如何解决这个问题的:

1) 将 Ninject 绑定移动到使用它的特定应用程序(更高级别)。

2) 使构造函数注入参数Optional

namespace Framework
{
    public class ExampleClass
    {
        private readonly IUsesExternalDll _usesExternalDll;

        public ExampleClass([Optional] IUsesExternalDll usesExternalDll)
        {
            _usesExternalDll = usesExternalDll;
        }
    }
}

可选属性将导致仅在存在绑定时才被实例化。由于我将绑定移至正在使用它的特定应用程序,因此在所有其他应用程序中我不会收到 Could not load file or assembly 错误,因为 UsesExternalDll 未实例化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2020-10-24
    相关资源
    最近更新 更多