.NET - Get default value for a reflected PropertyInfo

前端 未结 6 1696
鱼传尺愫
鱼传尺愫 2020-12-08 02:02

This is really stumping me today. I\'m sure its not that hard, but I have a System.Reflection.PropertyInfo object. I want to set its value based on the result of a database

相关标签:
6条回答
  • 2020-12-08 02:23

    The "null" trick will set it to the zero value for the type, which is not necessarily the same as the default for the property. Firstly, if it is a new object, why not just leave it alone? Alternatively, use TypeDescriptor:

    PropertyDescriptor prop = TypeDescriptor.GetProperties(foo)["Bar"];
    if (prop.CanResetValue(foo)) prop.ResetValue(foo);
    

    This respects both [DefaultValue] and the Reset{name}() patterns (as used by binding and serialization), making it very versatile and re-usable.

    If you are doing lots of this, you can also get a performance boost using TypeDescriptor instead of reflection, by re-using the PropertyDescriptorCollection and using HyperDescriptor (same code, but much faster than either refletion or raw TypeDescriptor).

    0 讨论(0)
  • 2020-12-08 02:30

    This is a more polished version that maintains the .NET Runtime's functionality without adding any unnecessary custom code.

    NOTE: This code written for .NET 3.5 SP1

    namespace System {
    
    public static class TypedDefaultExtensions {
    
        public static object ToDefault(this Type targetType) {
    
            if (targetType == null)
                throw new NullReferenceException();
    
            var mi = typeof(TypedDefaultExtensions)
                .GetMethod("_ToDefaultHelper", Reflection.BindingFlags.Static | Reflection.BindingFlags.NonPublic);
    
            var generic = mi.MakeGenericMethod(targetType);
    
            var returnValue = generic.Invoke(null, new object[0]);
            return returnValue;
        }
    
        static T _ToDefaultHelper<T>() {
            return default(T);
        }
    }
    

    }

    USAGE:

    PropertyInfo pi; // set to some property info
    object defaultValue = pi.PropertyType.ToDefault();
    
    public struct MyTypeValue { public int SomeIntProperty { get; set; }
    var reflectedType = typeof(MyTypeValue);
    object defaultValue2 = reflectedType.ToDefault();
    

    Rashad Rivera (OmegusPrime.com)

    0 讨论(0)
  • 2020-12-08 02:34

    Try the following methods, which I have written and tested against thousands of types:

        /// <summary>
        /// [ <c>public static T GetDefault&lt; T &gt;()</c> ]
        /// <para></para>
        /// Retrieves the default value for a given Type
        /// </summary>
        /// <typeparam name="T">The Type for which to get the default value</typeparam>
        /// <returns>The default value for Type T</returns>
        /// <remarks>
        /// If a reference Type or a System.Void Type is supplied, this method always returns null.  If a value type 
        /// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an 
        /// exception.
        /// </remarks>
        /// <seealso cref="GetDefault(Type)"/>
        public static T GetDefault<T>()
        {
            return (T) GetDefault(typeof(T));
        }
    
        /// <summary>
        /// [ <c>public static object GetDefault(Type type)</c> ]
        /// <para></para>
        /// Retrieves the default value for a given Type
        /// </summary>
        /// <param name="type">The Type for which to get the default value</param>
        /// <returns>The default value for <paramref name="type"/></returns>
        /// <remarks>
        /// If a null Type, a reference Type, or a System.Void Type is supplied, this method always returns null.  If a value type 
        /// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an 
        /// exception.
        /// </remarks>
        /// <seealso cref="GetDefault&lt;T&gt;"/>
        public static object GetDefault(Type type)
        {
            // If no Type was supplied, if the Type was a reference type, or if the Type was a System.Void, return null
            if (type == null || !type.IsValueType || type == typeof(void))
                return null;
    
            // If the supplied Type has generic parameters, its default value cannot be determined
            if (type.ContainsGenericParameters)
                throw new ArgumentException(
                    "{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type +
                    "> contains generic parameters, so the default value cannot be retrieved");
    
            // If the Type is a primitive type, or if it is another publicly-visible value type (i.e. struct), return a 
            //  default instance of the value type
            if (type.IsPrimitive || !type.IsNotPublic)
            {
                try
                {
                    return Activator.CreateInstance(type);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(
                        "{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe Activator.CreateInstance method could not " +
                        "create a default instance of the supplied value type <" + type +
                        "> (Inner Exception message: \"" + e.Message + "\")", e);
                }
            }
    
            // Fail with exception
            throw new ArgumentException("{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type + 
                "> is not a publicly-visible type, so the default value cannot be retrieved");
        }
    

    The first (generic) version of GetDefault is of course redundant for C#, since you may just use the default(T) keyword.

    Enjoy!

    0 讨论(0)
  • 2020-12-08 02:34

    I know this is an old post, but I like this twist on Darin Dimitrov's answer. It first checks for any DefualtValue attributes then uses Darin Dimitrov's answer:

    public static object GetDefaultValueForProperty(this PropertyInfo property)
        {
            var defaultAttr = property.GetCustomAttribute(typeof(DefaultValueAttribute));
            if (defaultAttr != null)
                return (defaultAttr as DefaultValueAttribute).Value;
    
            var propertyType = property.PropertyType;
            return propertyType.IsValueType ? Activator.CreateInstance(propertyType) : null;
        }
    
    0 讨论(0)
  • 2020-12-08 02:35
    object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
    
    0 讨论(0)
  • 2020-12-08 02:39

    I believe if you just do

    prop.SetValue(obj,null,null);
    

    If it's a valuetype, it'll set it to the default value, if it's a reference type, it'll set it to null.

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