2016-11-20 26 views
0

有没有什么办法可以告诉Visual Studio为我构建一个.dll,它只会在加载另一个引用(托管)库时存在,但仍然将其作为参考?是否有可选的库引用? (对于可修改的Mod)

基本上我想能够从外部库内部的类继承,只有当外部类存在时我才会初始化它。

更详细的解释:

  • 我做了一个改装API游戏(通过Assembly.LoadFrom)
  • 我想MODS的是moddable。可以说,我有2个Mods Mod A和Mod B. Mod A提供了添加额外功能的静态注册表。所以在Mod B中,我正在检查是否加载了Mod A,如果是,则使用Mod As静态注册表来注册我的addtions。
  • 问题是,为了这样做没有编译错误,我必须在Mod B的Visual Studio项目中添加Mod A作为参考 - 这导致如果Mod A不存在,Mod B将无法加载。但它应该是一个可选的参考:/

类似“懒库引用”将是完美的 - 其中一个lib引用只在实际需要时加载。

回答

2

您应该了解一下MEF如何工作(Managed Extensibility Framework),因为它在设计时考虑了这种插件场景。

这也是你应该考虑如何在界面而不是继承的基础上抽象化的方式。我相信你可以用动态类型和反射来做一些聪明的事情,但我也认为这很可能会变得复杂,因此在同一时间容易出错。

您还可以使用Lazy<T>确保仅在需要时才通过外部依赖关系的惰性实例化加载。您也不必为这些插件dll添加静态引用。您可以扫描实现抽象接口定义的库和类型的目录。

我也有点担心你为什么要抽象一个依赖于另一个抽象(Mod B检查Mod A),这在某种程度上听起来有问题 - 可以说是“泄漏”的抽象。

如果你真的必须有一种方法让这些插件一起合作,你可以使用自定义属性方法,这样一个mod可以声明一个依赖关系。

public class ModDependency : Attribute 
{ 
    public string DependsOn { get; set; } 
} 

但最终你将有一些协调在主应用程序代码,然后在运行时提供这些插件实例引用做。

+0

是的,我想避免使用反射/动态类型。谢谢我将读入MEF – Tyron

+0

就像上面提到的''TypeBuilder''是关于反射的,所以选项不在表格中。我会研究改变你当前的方法,以便使用可以在这些外部依赖中实现的“接口”。 – Jammer

+0

感谢您的额外信息 - 我不认为懒惰将工作,因为它似乎CLR会尝试加载引用的库,甚至没有创建一个有问题的类的实例(也不访问任何静态变量)。看起来,只要有任何类使用引用的库,它就会尝试加载引用的库,即使完全不使用类。 – Tyron

0

“.NET中的程序集由CLR按需加载,通常只有在使用该程序集中的类型的JIT'd方法之前,才会尝试程序集加载。 (来自不同的SO Answer

我知道了!显然我可以应用我的可选依赖关系的方法!

我发现问题是由于我加载这些mod的方式引起的。我正在遍历所有的程序集类型,检查任何实现IMod的类,这显然会导致正在讨论的类被加载,并且需要CLR加载依赖项。

现在我不打电话assembly.GetTypes()拨打assembly.GetExportedTypes(),并将相关课程声明为内部。现在,如果依赖关系不存在,它永远不会被加载。

+0

不,它不会“加载类”(你不能“加载”类)它将DLL加载到当前的AppDomain中以检索通过元数据在DLL中的类的列表。唯一一次创建对象的时候是使用''new''关键字。一旦DLL被加载到“AppDomain”中,它就不能被卸载。这样做*和*能够卸载DLL的唯一方法是在单独的AppDomain中完成所有这些。 – Jammer

+0

是的,但它只是似乎尝试加载引用的库,一旦有问题的类正在引用第一次。所以只要没有人触及该类,它就不会加载引用的lib – Tyron

相关问题