Setting the default value of a DateTime Property to DateTime.Now inside the System.ComponentModel Default Value Attrbute

后端 未结 21 1344
终归单人心
终归单人心 2020-11-29 22:53

Does any one know how I can specify the Default value for a DateTime property using the System.ComponentModel DefaultValue Attribute?

for example I try this:

相关标签:
21条回答
  • 2020-11-29 23:10

    You cannot do this with an attribute because they are just meta information generated at compile time. Just add code to the constructor to initialize the date if required, create a trigger and handle missing values in the database, or implement the getter in a way that it returns DateTime.Now if the backing field is not initialized.

    public DateTime DateCreated
    {
       get
       {
          return this.dateCreated.HasValue
             ? this.dateCreated.Value
             : DateTime.Now;
       }
    
       set { this.dateCreated = value; }
    }
    
    private DateTime? dateCreated = null;
    
    0 讨论(0)
  • 2020-11-29 23:11

    I needed a UTC Timestamp as a default value and so modified Daniel's solution like this:

        [Column(TypeName = "datetime2")]
        [XmlAttribute]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
        [Display(Name = "Date Modified")]
        [DateRange(Min = "1900-01-01", Max = "2999-12-31")]
        public DateTime DateModified {
            get { return dateModified; }
            set { dateModified = value; } 
        }
        private DateTime dateModified = DateTime.Now.ToUniversalTime();
    

    For DateRangeAttribute tutorial, see this awesome blog post

    0 讨论(0)
  • 2020-11-29 23:11

    With EF 7:

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    Column(TypeName = "datetime2")]
    DateTime? Dateadded { get; set; }
    

    migration script:

    AlterColumn("myschema.mytable", "Dateadded", c => c.DateTime(nullable: false, precision: 7, storeType: "datetime2", defaultValueSql: "getutcdate()"));
    

    result:

    ALTER TABLE [MySchema].[MyTable] ADD  CONSTRAINT [DF_MySchema.MyTable_Dateadded]  DEFAULT (getutcdate()) FOR [Dateadded]
    
    0 讨论(0)
  • 2020-11-29 23:12

    Creating a new attribute class is a good suggestion. In my case, I wanted to specify 'default(DateTime)' or 'DateTime.MinValue' so that the Newtonsoft.Json serializer would ignore DateTime members without real values.

    [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore )]
    [DefaultDateTime]
    public DateTime EndTime;
    
    public class DefaultDateTimeAttribute : DefaultValueAttribute
    {
        public DefaultDateTimeAttribute()
            : base( default( DateTime ) ) { }
    
        public DefaultDateTimeAttribute( string dateTime )
            : base( DateTime.Parse( dateTime ) ) { }
    }
    

    Without the DefaultValue attribute, the JSON serializer would output "1/1/0001 12:00:00 AM" even though the DefaultValueHandling.Ignore option was set.

    0 讨论(0)
  • 2020-11-29 23:14

    There is a way. Add these classes:

    DefaultDateTimeValueAttribute.cs

    using System;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using Custom.Extensions;
    
    namespace Custom.DefaultValueAttributes
    {
        /// <summary>
        /// This class's DefaultValue attribute allows the programmer to use DateTime.Now as a default value for a property.
        /// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. 
        /// </summary>
        [AttributeUsage(AttributeTargets.Property)]
        public sealed class DefaultDateTimeValueAttribute : DefaultValueAttribute
        {
            public string DefaultValue { get; set; }
            private object _value;
    
            public override object Value
            {
                get
                {
                    if (_value == null)
                        return _value = GetDefaultValue();
    
                    return _value;
                }
            }
    
            /// <summary>
            /// Initialized a new instance of this class using the desired DateTime value. A string is expected, because the value must be generated at runtime.
            /// Example of value to pass: Now. This will return the current date and time as a default value. 
            /// Programmer tip: Even if the parameter is passed to the base class, it is not used at all. The property Value is overridden.
            /// </summary>
            /// <param name="defaultValue">Default value to render from an instance of <see cref="DateTime"/></param>
            public DefaultDateTimeValueAttribute(string defaultValue) : base(defaultValue)
            {
                DefaultValue = defaultValue;
            }
    
            public static DateTime GetDefaultValue(Type objectType, string propertyName)
            {
                var property = objectType.GetProperty(propertyName);
                var attribute = property.GetCustomAttributes(typeof(DefaultDateTimeValueAttribute), false)
                    ?.Cast<DefaultDateTimeValueAttribute>()
                    ?.FirstOrDefault();
    
                return attribute.GetDefaultValue();
            }
    
            private DateTime GetDefaultValue()
            {
                // Resolve a named property of DateTime, like "Now"
                if (this.IsProperty)
                {
                    return GetPropertyValue();
                }
    
                // Resolve a named extension method of DateTime, like "LastOfMonth"
                if (this.IsExtensionMethod)
                {
                    return GetExtensionMethodValue();
                }
    
                // Parse a relative date
                if (this.IsRelativeValue)
                {
                    return GetRelativeValue();
                }
    
                // Parse an absolute date
                return GetAbsoluteValue();
            }
    
            private bool IsProperty
                => typeof(DateTime).GetProperties()
                    .Select(p => p.Name).Contains(this.DefaultValue);
    
            private bool IsExtensionMethod
                => typeof(DefaultDateTimeValueAttribute).Assembly
                    .GetType(typeof(DefaultDateTimeExtensions).FullName)
                    .GetMethods()
                    .Where(m => m.IsDefined(typeof(ExtensionAttribute), false))
                    .Select(p => p.Name).Contains(this.DefaultValue);
    
            private bool IsRelativeValue
                => this.DefaultValue.Contains(":");
    
            private DateTime GetPropertyValue()
            {
                var instance = Activator.CreateInstance<DateTime>();
                var value = (DateTime)instance.GetType()
                    .GetProperty(this.DefaultValue)
                    .GetValue(instance);
    
                return value;
            }
    
            private DateTime GetExtensionMethodValue()
            {
                var instance = Activator.CreateInstance<DateTime>();
                var value = (DateTime)typeof(DefaultDateTimeValueAttribute).Assembly
                    .GetType(typeof(DefaultDateTimeExtensions).FullName)
                    .GetMethod(this.DefaultValue)
                    .Invoke(instance, new object[] { DateTime.Now });
    
                return value;
            }
    
            private DateTime GetRelativeValue()
            {
                TimeSpan timeSpan;
                if (!TimeSpan.TryParse(this.DefaultValue, out timeSpan))
                {
                    return default(DateTime);
                }
    
                return DateTime.Now.Add(timeSpan);
            }
    
            private DateTime GetAbsoluteValue()
            {
                DateTime value;
                if (!DateTime.TryParse(this.DefaultValue, out value))
                {
                    return default(DateTime);
                }
    
                return value;
            }
        }
    }
    

    DefaultDateTimeExtensions.cs

    using System;
    
    namespace Custom.Extensions
    {
        /// <summary>
        /// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. See usage for more information.
        /// </summary>
        public static class DefaultDateTimeExtensions
        {
            public static DateTime FirstOfYear(this DateTime dateTime)
                => new DateTime(dateTime.Year, 1, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
    
            public static DateTime LastOfYear(this DateTime dateTime)
                => new DateTime(dateTime.Year, 12, 31, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
    
            public static DateTime FirstOfMonth(this DateTime dateTime)
                => new DateTime(dateTime.Year, dateTime.Month, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
    
            public static DateTime LastOfMonth(this DateTime dateTime)
                => new DateTime(dateTime.Year, dateTime.Month, DateTime.DaysInMonth(dateTime.Year, dateTime.Month), dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
        }
    }
    

    And use DefaultDateTimeValue as an attribute to your properties. Value to input to your validation attribute are things like "Now", which will be rendered at run time from a DateTime instance created with an Activator. The source code is inspired from this thread: https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. I changed it to make my class inherit with DefaultValueAttribute instead of a ValidationAttribute.

    0 讨论(0)
  • 2020-11-29 23:15

    A simple solution if you are using the Entity Framework is the add a partical class and define a constructor for the entity as the framework does not define one. For example if you have an entity named Example you would put the following code in a seperate file.

    namespace EntityExample
    {
        public partial class Example : EntityObject
        {
            public Example()
            {
                // Initialize certain default values here.
                this._DateCreated = DateTime.Now;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题