Reset System.Lazy

前端 未结 3 1110
小鲜肉
小鲜肉 2021-01-01 08:46

In a business class I have :

 class Employee{

      public Employee() {
          m_Manager = new Lazy( () => return myRepository.GetManag         


        
相关标签:
3条回答
  • 2021-01-01 09:15

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-01 09:21

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

    0 讨论(0)
  • 2021-01-01 09:22

    Before you re-instanciate the Lazy you can also add a condition for reseting only if it was initalized "if(m_Manager.IsValueCreated)".

    0 讨论(0)
提交回复
热议问题