C# 从动态加载的控制器中无法访问静态
我这里有一个插件系统,它检查程序集的基类实现。一个基类应该提供一个API,但当我点击控制器时,静态变量会忘记它们的值,并且总是返回它们的默认值 插件系统创建如下模块实例:C# 从动态加载的控制器中无法访问静态,c#,.net-core,asp.net-core-mvc,C#,.net Core,Asp.net Core Mvc,我这里有一个插件系统,它检查程序集的基类实现。一个基类应该提供一个API,但当我点击控制器时,静态变量会忘记它们的值,并且总是返回它们的默认值 插件系统创建如下模块实例: var assembly = Assembly.LoadFile(@"absolute\path\to\TestModule.dll"); var types = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(ModuleBase))); ModuleBase
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 class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
}
到目前为止效果不错。插件基本类型尽可能少:
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);
}
}
没什么特别的,真的。但是,当我现在实现一个访问我的StaticTest
变量的控制器时,它的值是0:
public class TestController : ControllerBase
{
[Route("Test")]
[HttpGet]
public ActionResult<int> GetStatics()
{
return TestModule.StaticTest;
}
}
公共类TestController:ControllerBase
{
[路线(“测试”)]
[HttpGet]
公共操作结果GetStatics()
{
返回TestModule.StaticTest;
}
}
如果我放弃插件方法,而是直接从控制台应用程序创建WebHost
,一切都会按预期工作,控制器返回3
我怀疑MVC在不同的AppDomain
中启动控制器,但情况似乎并非如此,因为AppDomain.CurrentDomain.FriendlyName
和AppDomain.CurrentDomain.Id
不会更改,并且不会调用AppDomain.CurrentDomain.DomainUnload
任何想法都是受欢迎的,我现在完全不知所措,我觉得我错过了整个事情的一些基本概念。您有一个名为
Test
的ivar,您正在访问一个名为StaticTest
的成员,该成员似乎没有定义。我的假设是您在这个问题中错误地命名了ivar,它应该是StaticTest
,而不是Test
基于这种假设,问题是您已经将动态创建的对象强制转换为ModuleBase
,但是TestModule
上存在StaticTest
。因此,除非您强制转换到TestModule
,否则无法访问StaticTest
,因为它是在那里定义的
编辑
对不起,我对控制器代码关注不够。真正的问题与上述类似,但与执行有关。您还没有显示调用它的位置,但是我假设您在某处调用它,或者关于为什么静态没有值的答案将非常明显。但是,如果您的实例被键入为
ModuleBase
,它将调用ModuleBase.Execute()
,而不是TestModule.Execute()
,即使它实际上是一个TestModule
实例。只有在使用实际键入为TestModule
的内容时,才会调用正确的Execute
override 您有一个名为Test
的ivar,您正在访问一个名为StaticTest
的成员,该成员似乎没有定义。我的假设是您在这个问题中错误地命名了ivar,它应该是StaticTest
,而不是Test
基于这种假设,问题是您已经将动态创建的对象强制转换为ModuleBase
,但是TestModule
上存在StaticTest
。因此,除非您强制转换到TestModule
,否则无法访问StaticTest
,因为它是在那里定义的
编辑
对不起,我对控制器代码关注不够。真正的问题与上述类似,但与执行有关。您还没有显示调用它的位置,但是我假设您在某处调用它,或者关于为什么静态没有值的答案将非常明显。但是,如果您的实例被键入为
ModuleBase
,它将调用ModuleBase.Execute()
,而不是TestModule.Execute()
,即使它实际上是一个TestModule
实例。只有在使用实际键入为TestModule
的内容时,才会调用正确的Execute
override 感谢@Chris Pratt指出这一点,我已经相应地编辑了我的问题。在写这篇文章的时候漏掉了。我有一些最小的代码来隔离问题,但是我没有一致地重命名变量。缺少的Execute
只是在代码块下面格式错误。该变量已初始化,中间未被覆盖。感谢@Chris Pratt指出这一点,我已相应地编辑了我的问题。在写这篇文章的时候漏掉了。我有一些最小的代码来隔离问题,但是我没有一致地重命名变量。缺少的Execute
只是在代码块下面格式错误。该变量已初始化,并且在两者之间未被覆盖。到目前为止效果良好。现在我在另一个项目中实现了一个插件:
this。什么意思?你怎么知道execute被调用了?你有日志记录吗?您确定(像真的、真的确定)您引用的StaticTest属性是正确的类型,并且不是基类型上具有类似名称的属性吗?你所描述的似乎是不可能的,所以我假设发生了什么事。@A.Chiesa:我肯定我引用的是来自TestModule
的静态变量,因为该变量没有在基类型中定义。为了清楚起见,我相应地更新了问题。如果我将TestModule
包装到控制台应用程序中,并使用new TestModule().Execute()
运行它,那么一切都会按预期运行。现在的问题是:您如何知道在MVC中调用了TestModule.Execute
方法?您是否在方法内部记录(到控制台或您使用的任何日志记录工具)?您确定找到的类型是TestModule
?因为项目是从Visual Studio启动的,所以我只需在TestModule.Execute
中设置一个断点。我还调查了加载程序中的类型
(第一个代码序列号)