C# Lazy Loaded Automatic Properties

前端 未结 12 2137
执笔经年
执笔经年 2020-12-04 11:08

In C#,

Is there a way to turn an automatic property into a lazy loaded automatic property with a specified default value?

Essentially, I am trying to turn th

相关标签:
12条回答
  • 2020-12-04 11:58

    https://github.com/bcuff/AutoLazy uses Fody to give you something like this

    public class MyClass
    {
        // This would work as a method, e.g. GetSettings(), as well.
        [Lazy]
        public static Settings Settings
        {
            get
            {
                using (var fs = File.Open("settings.xml", FileMode.Open))
                {
                    var serializer = new XmlSerializer(typeof(Settings));
                    return (Settings)serializer.Deserialize(fs);
                }
            }
        }
    
        [Lazy]
        public static Settings GetSettingsFile(string fileName)
        {
            using (var fs = File.Open(fileName, FileMode.Open))
            {
                var serializer = new XmlSerializer(typeof(Settings));
                return (Settings)serializer.Deserialize(fs);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-04 12:01

    Probably the most concise you can get is to use the null-coalescing operator:

    get { return _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce()); }
    
    0 讨论(0)
  • 2020-12-04 12:01

    I don't think this is possible with pure C#. But you could do it using an IL rewriter like PostSharp. For example it allows you to add handlers before and after functions depending on attributes.

    0 讨论(0)
  • 2020-12-04 12:02

    There is a new feature in C#6 called Expression Bodied Auto-Properties, which allows you to write it a bit cleaner:

    public class SomeClass
    { 
       private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
    
       public string SomeVariable 
       {
          get { return _someVariable.Value; }
       }
    }
    

    Can now be written as:

    public class SomeClass
    {
       private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
    
       public string SomeVariable => _someVariable.Value;
    }
    
    0 讨论(0)
  • 2020-12-04 12:03

    I did it like this:

    public static class LazyCachableGetter
    {
        private static ConditionalWeakTable<object, IDictionary<string, object>> Instances = new ConditionalWeakTable<object, IDictionary<string, object>>();
        public static R LazyValue<T, R>(this T obj, Func<R> factory, [CallerMemberName] string prop = "")
        {
            R result = default(R);
            if (!ReferenceEquals(obj, null))
            {
                if (!Instances.TryGetValue(obj, out var cache))
                {
                    cache = new ConcurrentDictionary<string, object>();
                    Instances.Add(obj, cache);
    
                }
    
    
                if (!cache.TryGetValue(prop, out var cached))
                {
                    cache[prop] = (result = factory());
                }
                else
                {
                    result = (R)cached;
                }
    
            }
            return result;
        }
    }
    

    and later you can use it like

           public virtual bool SomeProperty => this.LazyValue(() =>
        {
            return true; 
        });
    
    0 讨论(0)
  • 2020-12-04 12:06

    I'm a big fan of this idea, and would like to offer up the following C# snippet which I called proplazy.snippet.(you can either import this or paste it into the standard folder which you can get from the Snippet Manager)

    Here's a sample of its output:

    private Lazy<int> myProperty = new Lazy<int>(()=>1);
    public int MyProperty { get { return myProperty.Value; } }
    

    Here's the snippet file contents: (save as proplazy.snippet)

    <?xml version="1.0" encoding="utf-8" ?>
    <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
        <CodeSnippet Format="1.0.0">
            <Header>
                <Title>proplazy</Title>
                <Shortcut>proplazy</Shortcut>
                <Description>Code snippet for property and backing field</Description>
                <Author>Microsoft Corporation</Author>
                <SnippetTypes>
                    <SnippetType>Expansion</SnippetType>
                </SnippetTypes>
            </Header>
            <Snippet>
                <Declarations>
                    <Literal>
                        <ID>type</ID>
                        <ToolTip>Property type</ToolTip>
                        <Default>int</Default>
                    </Literal>
                    <Literal>
                        <ID>field</ID>
                        <ToolTip>The variable backing this property</ToolTip>
                        <Default>myVar</Default>
                    </Literal>
                    <Literal>
                        <ID>func</ID>
                        <ToolTip>The function providing the lazy value</ToolTip>
                    </Literal>
                    <Literal>
                        <ID>property</ID>
                        <ToolTip>Property name</ToolTip>
                        <Default>MyProperty</Default>
                    </Literal>
    
                </Declarations>
                <Code Language="csharp"><![CDATA[private Lazy<$type$> $field$ = new Lazy<$type$>($func$);
                public $type$ $property$ { get{ return $field$.Value; } }
                $end$]]>
                </Code>
            </Snippet>
        </CodeSnippet>
    </CodeSnippets>
    
    0 讨论(0)
提交回复
热议问题