C# 使用Prism和MEF多次初始化静态变量 上下文

C# 使用Prism和MEF多次初始化静态变量 上下文,c#,mef,composite-application,prism-6,C#,Mef,Composite Application,Prism 6,我有一个InteractionWindowPresenter类负责创建窗口。其中一些可能是模态窗口,我想保留一个计数器,记录打开的模态窗口的数量,以便通知应用程序的其他部分 因此,我在类中添加了一个\u modalsCount变量,在打开或关闭模式窗口时更新: public class InteractionWindowPresenter<TWindow, TNotification> where TWindow : System.Windows.Window whe

我有一个
InteractionWindowPresenter
类负责创建窗口。其中一些可能是模态窗口,我想保留一个计数器,记录打开的模态窗口的数量,以便通知应用程序的其他部分

因此,我在类中添加了一个
\u modalsCount
变量,在打开或关闭模式窗口时更新:

public class InteractionWindowPresenter<TWindow, TNotification>
    where TWindow : System.Windows.Window
    where TNotification : Prism.Interactivity.InteractionRequest.INotification
{
   private static int _modalsCount = 0;

   ...

   private bool _useModalWindow;

   public InteractionWindowPresenter(InteractionRequest<TNotification> request, 
      bool useModalWindow = false)
   {
      _useModalWindow = useModalWindow;
   }

   public void Show()
   {
      var window = ...

      window.Closed += (s, e) =>
      {
         if (_useModalWindow)
         {
             _modalsCount = Math.Max(0, --_modalsCount);

             if (_modalsCount == 0)
                 ServiceLocator.Current.GetInstance<IEventAggregator>()
                    .GetEvent<ModalStatusChanged>().Publish(false);
         }       
      };

      if (_useModalWindow)
      {
         _modalsCount++;

         ServiceLocator.Current.GetInstance<IEventAggregator>()
            .GetEvent<ModalStatusChanged>().Publish(true);

         window.ShowDialog();
      }
      else
         window.Show();
   }
}
InteractionWindowPresenter
类在所有模块以及其他基础结构程序集中直接引用的基础结构程序集中定义。它不被launcher应用程序引用,它只是一个
MefBootstrapper
。因此,MEF用于合成

问题 在
\u modalsCount
初始化行上设置断点表明,在创建
InteractionWindowPresenter
实例时不会执行断点。相反,它在每个模块中使用变量的第一次(并且仅在该次)执行,即从每个模块调用
Show
方法的第一次。因此,每个模块都有自己的值,在该特定模块的所有实例中共享

我知道延迟评估是由于。然而,我希望整个应用程序只进行一次评估,而不是每个模块

我还尝试在静态构造函数中执行初始化:

static int _modalsCount;

static InteractionWindowPresenter()
{
    _modalsCount = 0;
}
在这种情况下,在执行实例构造函数之前调用静态构造函数,但每次创建实例时都会调用静态构造函数。因此,变量似乎不再是静态的

据我了解。因此,由于我的所有程序集(模块和基础结构)都位于相同的
AppDomain
,因此不应该发生这种情况。我在这两个假设中有错吗

到目前为止一直在工作 创建一个简单的类来保存计数器可以避免此问题:

static class ModalsCounter
{
    private static int _modalsCount = 0;

    public static int Increment()
    {
        return ++_modalsCount;
    }

    public static int Decrement()
    {
        _modalsCount = Math.Max(0, --_modalsCount);
        return _modalsCount;
    }
}
因此,将对
\u modalsCount
的调用替换为:

ModalsCounter.Increment();

ServiceLocator.Current.GetInstance<IEventAggregator>()
   .GetEvent<ModalStatusChanged>().Publish(true);
ModalsCounter.Increment();
ServiceLocator.Current.GetInstance()
.GetEvent().Publish(true);
以及:

if(\u useModalWindow&&ModalCounter.Decrement()==0)
ServiceLocator.Current.GetInstance()
.GetEvent().Publish(false);


那么我在这里错过了什么?我是否误解了静态变量的生命周期和范围,或者是Prism模块和/或MEF干扰了我?

每个类型只创建一次静态变量。由于您使用的是泛型类型,因此创建的类型数将等于您在初始值设定项中使用的类型变量组合数。这就是为什么在非泛型类中隐藏静态是有效的(无论如何可能是一种更好的模式)。

为每种类型创建一次静态。由于您使用的是泛型类型,因此创建的类型数将等于您在初始值设定项中使用的类型变量组合数。这就是为什么在非泛型类中隐藏静态有效(无论如何可能是更好的模式)。

您的类是泛型的,每个构造的泛型类型(指定了类型参数)都是单独的类型。它们中的每一个都有自己的静态成员集

从第4.4.2节开始,打开和关闭类型:

每个封闭构造类型都有自己的静态变量集,这些静态变量不与任何其他封闭构造类型共享。由于开放类型在运行时不存在,因此不存在与开放类型关联的静态变量

您可以进行一个简单的测试:

public class Test<T>
{
    public static object obj = new object();
}

Console.WriteLine(object.ReferenceEquals(Test<string>.obj, Test<object>.obj)); // false
公共类测试
{
公共静态对象obj=新对象();
}
Console.WriteLine(object.ReferenceEquals(Test.obj,Test.obj));//错误的

您的解决方法(将静态计数器保留在非泛型类中)是正确的。

您的类是泛型的,每个构造的泛型类型(指定了类型参数)都是单独的类型。它们中的每一个都有自己的静态成员集

从第4.4.2节开始,打开和关闭类型:

每个封闭构造类型都有自己的静态变量集,这些静态变量不与任何其他封闭构造类型共享。由于开放类型在运行时不存在,因此不存在与开放类型关联的静态变量

您可以进行一个简单的测试:

public class Test<T>
{
    public static object obj = new object();
}

Console.WriteLine(object.ReferenceEquals(Test<string>.obj, Test<object>.obj)); // false
公共类测试
{
公共静态对象obj=新对象();
}
Console.WriteLine(object.ReferenceEquals(Test.obj,Test.obj));//错误的

您的解决方法(将静态计数器保留在非泛型类中)是正确的。

没错,我没有考虑泛型。使用字段初始值设定项和静态构造函数时执行的初始化数之间的差异是由于问题中提到的惰性,对吗?(事实上,前一种情况下的初始化数量与实际使用的不同类型实例的数量相关。)如果没有静态构造函数,初始化可能会延迟。如果从不调用
Show
方法,静态字段可能永远不会初始化。使用静态构造函数,初始化将在第一次使用类型之前发生。该死的,我没有考虑泛型。使用字段初始值设定项和静态构造函数时执行的初始化数之间的差异是由于问题中提到的惰性,对吗?(事实上,前一种情况下的初始化数量与实际使用的不同类型实例的数量相关。)如果没有静态构造函数,初始化可能会延迟。如果从不调用
Show
方法,静态字段可能永远不会初始化。使用静态构造函数时,初始化将在首次使用类型之前进行。
public class Test<T>
{
    public static object obj = new object();
}

Console.WriteLine(object.ReferenceEquals(Test<string>.obj, Test<object>.obj)); // false