根据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) { ... }
}
现在,问题可能看起来很愚蠢,但提到的全局变量 - 是我的私有和非静态字段以某种方式?我说他们不是,但我最近有点偏执,我试图谦虚。
此外,当我访问上下文并分配字段时,我创建了一个新对象并逐个分配字段(并非每个类都有方法克隆) 。序列化将要求我继承原始类并且违反要求。这是一种足够可靠的方法吗? (请记住我新获得的偏执狂。)
我试图在执行过程中造成问题但是到目前为止我已经看到了,这些问题并没有出现。当然,缺乏证据并不能证明缺席。我只是指出我不是懒惰的。相反意识到东西可能在比我最初看到的更深层次上是错误的。
答案 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
_b
和Execute()