If you are happy to use undocumented behavior and private fields, here is a way to do it:
public static void ResetPublicationOnly<T>(this Lazy<T> lazy) { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; LazyThreadSafetyMode mode = (LazyThreadSafetyMode)typeof(Lazy<T>).GetProperty("Mode", flags).GetValue(lazy, null); if (mode != LazyThreadSafetyMode.PublicationOnly) throw new InvalidOperationException("ResetPublicationOnly only works for Lazy<T> with LazyThreadSafetyMode.PublicationOnly"); typeof(Lazy<T>).GetField("m_boxed", flags).SetValue(lazy, null); }
And some test to use:
Lazy<string> val = new Lazy<string>(() => "hola" + DateTime.Now.Ticks, LazyThreadSafetyMode.PublicationOnly); val.ResetPublicationOnly(); //reset before initialized var str1 = val.Value; val.ResetPublicationOnly(); //reset after initialized var str2 = val.Value; Assert.AreNotEqual(str1, str2);
EDIT: Deprecated! This solution no longer works as directed by Keith. We have our own owr ResetLazy in Signum Framework
public interface IResetLazy { void Reset(); void Load(); Type DeclaringType { get; } } [ComVisible(false)] [HostProtection(Action = SecurityAction.LinkDemand, Resources = HostProtectionResource.Synchronization | HostProtectionResource.SharedState)] public class ResetLazy<T>: IResetLazy { class Box { public Box(T value) { this.Value = value; } public readonly T Value; } public ResetLazy(Func<T> valueFactory, LazyThreadSafetyMode mode = LazyThreadSafetyMode.PublicationOnly, Type declaringType = null) { if (valueFactory == null) throw new ArgumentNullException("valueFactory"); this.mode = mode; this.valueFactory = valueFactory; this.declaringType = declaringType ?? valueFactory.Method.DeclaringType; } LazyThreadSafetyMode mode; Func<T> valueFactory; object syncLock = new object(); Box box; Type declaringType; public Type DeclaringType { get { return declaringType; } } public T Value { get { var b1 = this.box; if (b1 != null) return b1.Value; if (mode == LazyThreadSafetyMode.ExecutionAndPublication) { lock (syncLock) { var b2 = box; if (b2 != null) return b2.Value; this.box = new Box(valueFactory()); return box.Value; } } else if (mode == LazyThreadSafetyMode.PublicationOnly) { var newValue = valueFactory(); lock (syncLock) { var b2 = box; if (b2 != null) return b2.Value; this.box = new Box(newValue); return box.Value; } } else { var b = new Box(valueFactory()); this.box = b; return b.Value; } } } public void Load() { var a = Value; } public bool IsValueCreated { get { return box != null; } } public void Reset() { if (mode != LazyThreadSafetyMode.None) { lock (syncLock) { this.box = null; } } else { this.box = null; } } }
Olmo Jun 06 2018-11-06T00: 00Z
source share