Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset System.Lazy

Tags:

c#-4.0

In a business class I have :

 class Employee{        public Employee() {           m_Manager = new Lazy<Manager>( () => return myRepository.GetManager(ManagerId); );       }       public int ManagerId { get; set;}       private Lazy<Manager> m_Manager;       public Manager Manager {            get {                return m_Manager.Value;           }       }  } 

This is working correctly, the custom repository is called only if accessing the Manager property. Now I want to "reset" my manager property if the ManagerId changed. How to do that ?

I can do :

 class Employee{        public Employee() {           m_Manager = new Lazy<Manager>( () => return myRepository.GetManager(ManagerId); );       }       private int m_ManagerId;       public int ManagerId {            get { return m_ManagerId;}           set {                 if(m_ManagerId != value)                {                     m_ManagerId = value;                     m_Manager = new Lazy<Manager>( () => return myRepository.GetManager(ManagerId); );                }           }       }       private Lazy<Manager> m_Manager;       public Manager Manager {            get {                return m_Manager.Value;           }       }  } 

Is there a cleaner way to do that ? Isn't there a m_Manager.Reset() or something like this ?

like image 515
Steve B Avatar asked May 11 '11 08:05

Steve B


People also ask

How do you reset Lazy?

Unplug the pump from the socket. Whilst the pump is unplugged press the thermal reset button in and hold for 5 seconds.

Is system Lazy thread-safe?

By default, Lazy<T> objects are thread-safe. That is, if the constructor does not specify the kind of thread safety, the Lazy<T> objects it creates are thread-safe.

How does lazy initialization work?

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

What is Lazy <> in C#?

Lazy initialization is a technique that defers the creation of an object until the first time it is needed. In other words, initialization of the object happens only on demand. Note that the terms lazy initialization and lazy instantiation mean the same thing—they can be used interchangeably.


2 Answers

Lazy<T> does not define a Reset() method. What you've implemented looks fine I think.

like image 148
Nathan Avatar answered Oct 02 '22 12:10

Nathan


If you are happy with using undocumented behaviour and private fields, here is a method 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 for usage:

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 pointed by Keith. We have build owr own 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;         }     } } 
like image 44
Olmo Avatar answered Oct 02 '22 13:10

Olmo