在属性中执行初始化是一个好习惯吗?

本文关键字:一个 好习惯 属性 执行 初始化 | 更新日期: 2023-09-27 18:17:28

我有一个类PluginProvider,它使用PluginLoader组件从文件系统加载插件(managed/native)。在PluginProvider类中,目前定义了一个名为'PluginTypes'的属性,它在get()上调用'InitializePlugins'实例方法。

class PluginProvider
 {
   IEnumerable<IPluginType> PluginTypes
   {
     get
     {
        //isInitialized is set inside InitializePlugins method
        if(!isInitialized)
        {
           InitializePlugins(); //contains thread safe code
        }
        //_pluginTypes is set within InitializePlugins method
        return _pluginTypes;
     }
   }
 }

我正在考虑重构这段代码。我想知道在属性中进行这种初始化是否合适。我知道不能在物业内进行繁重的操作。但是当我检查这个链接:http://msdn.microsoft.com/en-us/library/vstudio/ms229054.aspx时,发现这个"特别是,访问网络或文件系统的操作(除了一次初始化)应该很可能是方法,而不是属性。"现在我有点困惑了。请帮助。

在属性中执行初始化是一个好习惯吗?

  • 如果你想尽可能延迟初始化,并且你不知道何时你的属性(或属性)将被调用,你所做的是好的。
  • 如果你想延迟并且你可以控制何时你的属性将被第一次调用,那么你可能想让你的方法InitializePlugins()公开,并在访问属性之前显式调用它。此选项还提供了异步初始化的可能性。例如,您可以让一个InitializePluginsAsync()返回一个Task
  • 如果延迟初始化不是一个大问题,那么只需在构造函数中执行初始化。

这当然是个人喜好的问题。但是我要做什么取决于你要做的手术的长度。如果加载插件需要时间,我会创建一个公共方法,任何用户在使用类之前都需要调用该方法。另一种方法是将方法放在构造函数中,但是IMO构造函数应该尽可能快地返回,并且应该包含字段/属性初始化。

class PluginProvider
{
    private bool _isInitialized;
    IEnumerable<IPluginType> PluginTypes { get; set;}
    public void Initialize()
    {
        if (_isInitialized)
        {
             return;
        }      
        InitializePlugins();
        _isInitialized = true;  
    }
}

注意,这样做的缺点是,您必须确保在使用任何操作之前调用Initialize方法。

支持这种方法的另一件事是异常处理。我确信您不会希望您的构造函数抛出任何类型的IOException,以防它无法从文件系统加载类型。

任何初始化类型的代码都应该在构造函数中完成,这样你就知道它只会被调用一次。

public class PluginProvider
{
   IEnumerable<IPluginType> PluginTypes
   {
      get
      {
        return _pluginTypes;
      }
   }
   public PluginProvider()
   {
      InitializePlugins();
   }
}

您在这里所做的称为延迟初始化。您正在推迟执行一个可能代价高昂的操作,直到需要其输出的时刻。

现在,这不是一个绝对的规则。如果你的InitializePlugins方法需要很长时间才能完成,这可能会影响用户体验,那么你可以考虑将其移动到一个公共方法中,甚至使其异步,并在属性之外调用它:在应用程序启动时或当你找到一个合适的时刻调用一个持久的操作。

否则,如果它是一个短暂的一次性的东西,它可以留在那里。正如我所说,这不是绝对的规则。一般来说,这些都是一些适用于特定情况的指导原则。