【发布时间】:2018-01-17 04:35:23
【问题描述】:
我正在编写一个简单的插件,偶然发现 contractType.IsAssignableFrom(pluginType) 根据加载顺序返回不同的结果。
在插件上调用 IsAssignableFrom 按预期返回 True。
但是如果我在加载插件之前加载合同程序集,插件上的 IsAssignableFrom返回 False。
我正在运行 Win10 和 dotnet4.7,但我怀疑这有什么相关性。
代码
[TestMethod]
public void SimplyLoadingPlugin_Succeeds()
{
var plugin = Assembly.LoadFrom(PluginPathFilename);
var res = typeof(Contract).IsAssignableFrom(plugin.GetExportedTypes().Single());
Assert.IsTrue(res); // Succeeds.
}
[TestMethod]
public void LoadingContractAndThenPlugin_Fails()
{
var contract = Assembly.LoadFrom(ContractPathFilename);
var plugin = Assembly.LoadFrom(PluginPathFilename);
var res = typeof(Contract).IsAssignableFrom(plugin.GetExportedTypes().Single());
Assert.IsTrue(res); // Fails.
}
为了让测试更难:
如果我自己运行LoadingContractAndThenPlugin_Fails 测试失败。但是如果我一起运行测试,它取决于顺序。首先运行 SimplyLoadingPlugin_Succeeds 和最后运行 LoadingContractAndThenPlugin_Fails 会使两个测试都变为绿色,但以相反的顺序运行它们会使两者都失败。
所以不知何故,在插件之前加载合同给我带来了一些麻烦。
我在 GAC 中看不到任何相关内容。
以下是所需的所有文件。中的路径可能需要更新。
4 个项目,每个项目一个文件。 1 个解决方案。
Contract.cs(一个库项目)
public abstract class Contract
{
public abstract int Version { get; set; }
}
Plugin.cs(一个库项目)
public class Plugin : Contract
{
public override int Version { get; set; }
}
Tests.cs(一个测试项目)
[TestClass]
public class Tests
{
private const string PluginPath = @"C:\DATA\Projekt\LoadFromOrder\Plugin\bin\Debug";
private string PluginPathFilename = Path.Combine(PluginPath, "Plugin.dll");
private string ContractPathFilename = Path.Combine(PluginPath, "Contract.dll");
[TestMethod]
public void SimplyLoadingPlugin_Succeeds()
{
var plugin = Assembly.LoadFrom(PluginPathFilename);
var res = typeof(Contract).IsAssignableFrom(plugin.GetExportedTypes().Single());
Assert.IsTrue(res); // Succeeds.
}
[TestMethod]
public void LoadingContractAndThenPlugin_Fails()
{
var contract = Assembly.LoadFrom(ContractPathFilename);
var plugin = Assembly.LoadFrom(PluginPathFilename);
var res = typeof(Contract).IsAssignableFrom(plugin.GetExportedTypes().Single());
Assert.IsTrue(res); // Fails.
}
// BEGIN ---- Update. ----
[TestMethod]
public void LoadingPluginFromTestProject_Succeeds()
{
var contract = Assembly.LoadFrom(
@"C:\DATA\Projekt\LoadFromOrder\TestProject\bin\Debug\Contract.dll");
var plugin = Assembly.LoadFrom(PluginPathFilename);
var res = typeof(Contract.Contract).IsAssignableFrom(plugin.GetExportedTypes().Single());
Assert.IsTrue(res); // Succeeds.
}
// END ---- Update. ----
}
Program.cs(控制台项目)
class Program
{
static void Main(string[] args)
{
var tests = new Tests();
try
{
System.Console.WriteLine("Press A for Success and B for Fail.");
switch (System.Console.ReadKey(true).Key)
{
case ConsoleKey.A:
tests.SimplyLoadingPlugin_Succeeds();
break;
case ConsoleKey.B:
tests.LoadingContractAndThenPlugin_Fails();
break;
}
System.Console.WriteLine("SUCCESS");
}
catch (Exception exc)
{
System.Console.WriteLine($"FAIL: {exc.Message}");
}
}
}
【问题讨论】:
-
由于您的两个测试都直接引用
Contract类型,因此必须加载包含该类型的程序集,以便这些方法能够 JIT 编译。因此,我认为您并没有像想象的那样控制订购。 -
同意。
Assembly.LoadFromvsAssembly.LoadFile控制 不在我的手中。但不知何故,在加载插件之前加载合同,然后加载合同,这会有所不同。就像我已经将 Contract´ 加载到我的程序集中,然后它阻止 Plugin 找到 Contract´´。我只是回答了我自己的问题吗?但仍然没有补救措施。 -
我尝试使用 1 个控制台应用程序和 2 个类库项目在一个新解决方案中重新创建您的问题,但我无法获得您所描述的行为......你能不能尝试为您的问题创建Minimal, Complete, and Verifiable example,以便我们重新创建问题?
-
您确定您的 testproject 不包含任何可能导致对引用的 dll 之一进行重建的项目引用吗?
-
@bassfader 非常感谢您花时间解决我的问题。我已经为测试添加了类,因此路径常量的复制/粘贴和更新应该足以重现问题。我确实在重新启动的系统上创建了一个全新的解决方案并重现了该问题;运行他们成功的所有测试。运行
..._Fails测试失败。正是这个文本被复制到我的问题中。