【发布时间】:2019-12-04 20:42:00
【问题描述】:
我这里有一个插件系统,用于检查程序集以查找基类的实现。一个基类应该提供一个 API,但是当我点击控制器时,静态变量会忘记它们的值并总是返回它们的默认值。
插件系统像这样创建模块实例:
var assembly = Assembly.LoadFile(@"absolute\path\to\TestModule.dll");
var types = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(ModuleBase)));
ModuleBase instance = (ModuleBase)Activator.CreateInstance(types.FirstOrDefault());
instance.Execute();
到目前为止效果很好。插件基本类型尽可能小:
public abstract class ModuleBase
{
public abstract void Execute();
}
现在我在另一个项目中实现了一个插件:
public class TestModule : ModuleBase
{
public static int StaticTest;
public override void Execute()
{
StaticTest = 3; // variable is initialized with some non-default value
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.Build()
.RunAsync(cancellationTokenSource.Token);
}
}
Startup.cs 类如下所示:
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
}
没什么特别的,真的。但是,当我现在实现一个正在访问我的 StaticTest 变量的控制器时,它的值为 0:
public class TestController : ControllerBase
{
[Route("Test")]
[HttpGet]
public ActionResult<int> GetStatics()
{
return TestModule.StaticTest;
}
}
如果我放弃插件方法,而是直接从控制台应用程序创建WebHost,一切都会按预期工作,并且控制器返回 3。
我怀疑 MVC 会在不同的 AppDomain 中启动控制器,但情况似乎并非如此,因为 AppDomain.CurrentDomain.FriendlyName 和 AppDomain.CurrentDomain.Id 不会改变,AppDomain.CurrentDomain.DomainUnload 也不会被调用。
欢迎任何想法,我现在完全一无所知,我觉得我错过了整个事情的一些基本概念。
【问题讨论】:
-
That's working nice so far. Now I implement a plugin for that in a different project:这个。你的意思是?你怎么知道执行被调用?你有日志吗?您确定(非常非常确定)您引用的 StaticTest 属性是正确的类型,并且不是基类型上类似命名的属性吗?你所描述的似乎是不可能的,所以我会假设发生了什么事。 -
@A. Chiesa:我确定我引用了来自
TestModule的静态变量,因为该变量未在基本类型中定义。为清楚起见,我已相应地更新了问题。如果我将TestModule包装到控制台应用程序中并使用new TestModule().Execute()运行它,一切都会按预期工作。 -
那么现在的问题是:你怎么知道在MVC中调用了
TestModule.Execute方法?您是否在方法内记录(到控制台或您使用的任何记录工具)?你确定找到的类型是TestModule? -
好吧,既然项目是从Visual Studio启动的,我就简单的在
TestModule.Execute设置一个断点。我还调查了加载器中的types(第一个代码sn-p),它确实是一个包含单个TestModule类型的列表。 -
真的很尴尬,我用C#已经10多年了,但我完全不知道这里发生了什么。
标签: c# .net-core asp.net-core-mvc