如果你很高興與使用無證的行爲和私人領域,在這裏是做它的方法:
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);
}
而且一些試驗使用:
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);
編輯:棄用!該解決方案不再像Keith指出的那樣工作。我們在Signum的框架
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;
}
}
}
有點棘手,建立自己的OWR ResetLazy,但它可以被封裝成一種推廣方法,這可能非常簡化我的代碼。 THX – 2011-06-06 19:19:06
希望你不是在緊密循環 – 2012-11-29 21:03:42
看起來他們已經做了一些修改,以懶惰源代碼。這種方法不再起作用並且將引發異常 –
Keith
2013-01-31 17:16:22