Search code examples
c#lazy-loadingaoppostsharp

How to implement Lazy loading with PostSharp?


I would like to implement lazy loading on properties with PostSharp.

To make it short, instead of writing

SomeType _field = null;
private SomeType Field
{
    get
    {
        if (_field == null)
        {
            _field = LongOperation();
        }
        return _field;
    }
}

I would like to write

[LazyLoadAspect]
private object Field
{
    get
    {
        return LongOperation();
    }
}

So, I identify that I need to emit some code in the class to generate the backing field, as well as inside the getter method in order to implement the test.

With PostSharp, I was considering overriding CompileTimeInitialize, but I am missing the knowledge to get a handle over the compiled code.

EDIT: The question can be extended to any parameterless method like:

SomeType _lazyLoadedField = null;
SomeType LazyLoadableMethod ()
{
    if(_lazyLoadedField ==null)
    {
        // Long operations code...
        _lazyLoadedField = someType;
    }
    return _lazyLoadedField ;
}

would become

[LazyLoad]
SomeType LazyLoadableMethod ()
{
     // Long operations code...
     return someType;
}

Solution

  • After our comments, I think I know what you want now.

    [Serializable]
        public class LazyLoadGetter : LocationInterceptionAspect, IInstanceScopedAspect
        {
            private object backing;
    
            public override void OnGetValue(LocationInterceptionArgs args)
            {
                if (backing == null)
                {
                    args.ProceedGetValue();
                    backing = args.Value;
                }
    
                args.Value = backing;
            }
    
            public object CreateInstance(AdviceArgs adviceArgs)
            {
                return this.MemberwiseClone();
            }
    
            public void RuntimeInitializeInstance()
            {
    
            }
        }
    

    Test code

    public class test
        {
            [LazyLoadGetter]
            public int MyProperty { get { return LongOperation(); } }
        }