首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >.NET -获取反射PropertyInfo的默认值

.NET -获取反射PropertyInfo的默认值
EN

Stack Overflow用户
提问于 2009-01-02 16:32:01
回答 5查看 37K关注 0票数 65

今天真的把我难倒了。我确信这并不难,但我有一个System.Reflection.PropertyInfo对象。我想根据数据库查找的结果来设置它的值(比如ORM,将一个列映射回一个属性)。

我的问题是,如果DB返回值是DBNull,我只想将属性值设置为其默认值,这与调用:

代码语言:javascript
复制
value = default(T);  // where T is the type of the property.

然而,如果你给default()方法一个Type,它将不会被编译,这就是我所拥有的:

代码语言:javascript
复制
object myObj = ???; // doesn't really matter. some arbitrary class.
PropertyInfo myPropInf = ???; // the reflection data for a property on the myObj object.
myPropInf.SetValue(myObj, default(myPropInf.PropertyType), null);

上面的代码不能编译。默认(类型)无效。我也考虑过这样做:

代码语言:javascript
复制
object myObj = ???;
PropertyInfo myPropInf = ???;
myPropInf.SetValue(myObj, Activator.CreateInstance(myPropInf.PropertyType), null);

但是,如果Type是string,则会赋值为"new String()",但我确实想要"null",这是"default(string)“将返回的值。

那么我在这里错过了什么呢?我认为一种非常老套的方法是创建myObj的Type的新实例并复制属性,但这看起来很愚蠢……

代码语言:javascript
复制
object myObj = ???;
PropertyInfo  myPropInf = ???;
var blank = Activator.CreateInstance(myObj.GetType());
object defaultValue = myPropInf.GetValue(blank, null);
myPropInf.SetValue(myObj, defaultValue, null);

我不想浪费内存来创建一个全新的实例,只是为了获取属性的默认值。看起来很浪费。

有什么想法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-01-02 16:43:13

我相信只要你这么做

代码语言:javascript
复制
prop.SetValue(obj,null,null);

如果它是一个值类型,它会将它设置为默认值,如果它是一个引用类型,它会将它设置为null。

票数 61
EN

Stack Overflow用户

发布于 2009-01-02 16:37:31

代码语言:javascript
复制
object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
票数 55
EN

Stack Overflow用户

发布于 2011-10-24 05:42:37

尝试以下方法,我已经针对数千种类型编写并测试了这些方法:

代码语言:javascript
复制
    /// <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");
    }

对于C#来说,GetDefault的第一个(通用)版本当然是多余的,因为您可以只使用default(T)关键字。

享受吧!

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/407337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档