What is the best way to give a C# auto-property an initial value?

前端 未结 22 3389
死守一世寂寞
死守一世寂寞 2020-11-22 02:48

How do you give a C# auto-property an initial value?

I either use the constructor, or revert to the old syntax.

Using the Constructor:

22条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-22 03:20

    My solution is to use a custom attribute that provides default value property initialization by constant or using property type initializer.

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class InstanceAttribute : Attribute
    {
        public bool IsConstructorCall { get; private set; }
        public object[] Values { get; private set; }
        public InstanceAttribute() : this(true) { }
        public InstanceAttribute(object value) : this(false, value) { }
        public InstanceAttribute(bool isConstructorCall, params object[] values)
        {
            IsConstructorCall = isConstructorCall;
            Values = values ?? new object[0];
        }
    }
    

    To use this attribute it's necessary to inherit a class from special base class-initializer or use a static helper method:

    public abstract class DefaultValueInitializer
    {
        protected DefaultValueInitializer()
        {
            InitializeDefaultValues(this);
        }
    
        public static void InitializeDefaultValues(object obj)
        {
            var props = from prop in obj.GetType().GetProperties()
                        let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
                        where attrs.Any()
                        select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
            foreach (var pair in props)
            {
                object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
                                ? pair.Attr.Values[0]
                                : Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
                pair.Property.SetValue(obj, value, null);
            }
        }
    }
    

    Usage example:

    public class Simple : DefaultValueInitializer
    {
        [Instance("StringValue")]
        public string StringValue { get; set; }
        [Instance]
        public List Items { get; set; }
        [Instance(true, 3,4)]
        public Point Point { get; set; }
    }
    
    public static void Main(string[] args)
    {
        var obj = new Simple
            {
                Items = {"Item1"}
            };
        Console.WriteLine(obj.Items[0]);
        Console.WriteLine(obj.Point);
        Console.WriteLine(obj.StringValue);
    }
    

    Output:

    Item1
    (X=3,Y=4)
    StringValue
    

提交回复
热议问题