2016-08-24 35 views
0

经过很多次我需要实现一个Lazy<T>模式,它让我想到了将整个模式放入类中以隐藏延迟实现的想法。封装懒惰<T>

在“加载单配置对象为我服务”的情况下,我做了这样的事情:

public interface IConfigurationProvider<T> 
{ 
    T GetConfiguration(); 
} 

public abstract class SingletonConfigurationProvider<TConfiguration> : IConfigurationProvider<TConfiguration> 
{ 
    private static readonly Lazy<TConfiguration> _lazy = 
     new Lazy<TConfiguration>(_loadConfiguration); 

    private static Func<TConfiguration> _loadConfiguration; 

    private SingletonConfigurationProvider() { } 
    public SingletonConfigurationProvider(Func<TConfiguration> LoadConfig) 
    { 
     _loadConfiguration = LoadConfig; 
    } 

    public TConfiguration GetConfiguration() 
    { 
     return _lazy.Value; 
    } 
} 

我的目标是获得,从“外部”简单在做这个:

public class ConfigTest : SingletonConfigurationProvider<ObjectTest> 
{ 
    public ConfigTest() 
     : base(Load) 
    { 
    } 

    public static ObjectTest Load() 
    { 
     return new ObjectTest() 
     { 
      testInt = 3, 
      testString = "Hi" 
     }; 
    } 
} 

的要点是:

  • 它编译,但它打破了在运行时,用“TypeInitialization例外? n“表示_loadConfiguration不能为空。是否因为在构造函数SingletonConfigurationProvider之前构造了懒惰?
  • 是否有可能实现我想要的而不破坏单身人士的语义?
+3

你基本上是围绕2行代码构建一个抽象:静态字段和getter。是不是真的值得吗? – Sinatr

+1

问题可能出现在_loadConfiguration为空时初始化_lazy的第一行。尝试将初始化移动到您的重载构造函数。 – Sarathy

+0

@Sarathy在这种情况下_lazy不能只读 –

回答

1

您正在寻找的抽象是memoising函数。在这种函数中,您修改了getter函数,以便它实现“只执行一次”类型的模式。未经测试的代码,但大致;

public Func<T> Memoize(Func<T> slowFunction) { 
    bool evaluated = false; 
    T value = default(T); 

    return() => { 
     if (!evaluated) { 
      value = slowFunction(); 
      evaluated = true; 
     } 

     return value; 
    }; 
} 

所以,你现在有一个功能,你可以这样使用;

Func<TConfiguration> onceOnlyLoad = Memoise(Load); 

现在,您可以拨打onceOnlyLoad()多次,只要你喜欢,它会只加载的配置第一次调用它。

如果需要,您可以在内部使用Lazy<T>以提供相同的行为。由你决定。