不建议使用成员变量

时间:2015-05-28 12:30:16

标签: c# .net

根据MSDN,由于线程和缓存,不建议使用成员变量。请注意,这个问题涉及多个领域,虽然我确定它主要与.NET / C#相关,但可能结果是特定于CRM。它可能不会赢,但单挑可能是明智的。

虽然我已经牢牢掌握了可能出现的问题,但我并不完全确定我理解确切且准确的情况之外警告& #39;的限制。我所关注的确切报价如下。

  

为了提高性能,Microsoft Dynamics CRM会缓存插件实例。应该将插件的Execute方法编写为无状态,因为每次调用插件时都不会调用构造函数。此外,多个系统线程可以同时执行插件。所有每个调用状态信息都存储在上下文中,因此您不应使用全局变量或尝试将任何数据存储在成员变量中,以便在下一个插件调用期间使用,除非该数据是从提供给构造函数的配置参数中获取的。对插件注册的更改将导致插件重新初始化。

我的班级遵循以下原则。

public partial class Blopp : IPlugin
{
  private IPluginExecutionContext Context { get; set; }
  private Entity Target { get; set; }
  private IOrganizationService Service { get; set; }
  ...

  public Blopp() : this(String.Empty) { }
  public Blopp(String a) : this(a, String.Empty) { }
  public Blopp(String a, String b) { ... }

  public void Execute(IServiceProvider serviceProvider)
  {
    try
    {
      Assign(serviceProvider);
      DoStuff();
    }
    catch (Exception) { }
    finally { ... }
  }

  private void Assign(IServiceProvider serviceProvider) { ... }
}

现在,问题可能看起来很愚蠢,但提到的全局变量 - 是我的私有非静态字段以某种方式?我说他们不是,但我最近有点偏执,我试图谦虚。

此外,当我访问上下文并分配字段时,我创建了一个新对象并逐个分配字段(并非每个类都有方法克隆) 。序列化将要求我继承原始类并且违反要求。这是一种足够可靠的方法吗? (请记住我新获得的偏执狂。)

我试图在执行过程中造成问题但是到目前为止我已经看到了,这些问题并没有出现。当然,缺乏证据并不能证明缺席。我只是指出我不是懒惰的。相反意识到东西可能在比我最初看到的更深层次上是错误的。

2 个答案:

答案 0 :(得分:5)

不,私人成员不是全球变量。关键点是"您不应该使用全局变量尝试将任何数据存储在成员变量中,以便在下一个插件调用期间使用"

它表示如果您在Execute()中操纵私有(或全局)变量,Execute()的另一个调用可能同时在同一个实例上运行并覆盖您的私有(或全局变量,导致之后运行的代码显示意外行为。

所以,让它们成为局部变量:

private void Assign(IServiceProvider serviceProvider) 
{
    IPluginExecutionContext context;
    Entity target;
    IOrganizationService service;

    ...
}

这将确保每个调用堆栈只能访问自己的变量。

答案 1 :(得分:2)

要添加到CodeCaster的答案,您可以拥有的成员变量是通过构造函数初始化的成员变量。但是为了避免状态,它们应该是只读的,所以它们只能由构造函数设置:

public partial class Blopp : IPlugin
{
  private readonly string _a;
  private readonly string _b;

  public Blopp() : this(String.Empty) { }
  public Blopp(String a) : this(a, String.Empty) { }
  public Blopp(String a, String b) 
  {
      _a = a;
      _b = b;
  }

然后,您可以从_a

中安全地访问_bExecute()