今天这真的让我很难过.我确定它不是那么难,但我有一个System.Reflection.PropertyInfo对象.我想根据数据库查找的结果设置其值(想想ORM,将列映射回属性).
我的问题是如果DB返回的值是DBNull,我只想将属性值设置为默认值,与调用相同:
value = default(T); // where T is the type of the property.
但是,如果你给它一个Type,那么default()方法将无法编译,这就是我所拥有的:
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);
以上不编译.默认(类型)无效.我还想过:
object myObj = ???; PropertyInfo myPropInf = ???; myPropInf.SetValue(myObj, Activator.CreateInstance(myPropInf.PropertyType), null);
但是,如果Type是字符串,那将赋值"new String()",但我真的想要"null",这就是"default(string)"将返回的内容.
那我在这里错过了什么?我想一个非常hacky的方法是创建myObj的Type的新实例并复制属性,但这看起来很愚蠢......
object myObj = ???; PropertyInfo myPropInf = ???; var blank = Activator.CreateInstance(myObj.GetType()); object defaultValue = myPropInf.GetValue(blank, null); myPropInf.SetValue(myObj, defaultValue, null);
我宁愿不浪费内存来创建一个全新的实例,只是为了获得属性的默认值.似乎非常浪费.
有任何想法吗?
我相信如果你这样做
prop.SetValue(obj,null,null);
如果它是一个值类型,它会将它设置为默认值,如果它是一个引用类型,它会将它设置为null.
object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
"null"技巧会将其设置为类型的零值,该值不一定与属性的默认值相同.首先,如果它是一个新的对象,为什么不单独留下它?或者,使用TypeDescriptor
:
PropertyDescriptor prop = TypeDescriptor.GetProperties(foo)["Bar"]; if (prop.CanResetValue(foo)) prop.ResetValue(foo);
这既尊重[DefaultValue]
和Reset{name}()
模式(由绑定和序列化使用),使其非常通用和可重复使用.
如果你正在做大量的这个,你也可以用获得的性能提升TypeDescriptor
,而不是反射,通过-重新使用的PropertyDescriptorCollection
,并使用HyperDescriptor(相同的代码,但很多比任何refletion或原始更快TypeDescriptor
).
尝试以下方法,我已经编写并测试了数千种类型:
////// [ ///public static T GetDefault< T >() ] ////// Retrieves the default value for a given Type /// The Type for which to get the default value ///The default value for Type T ////// 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. /// ///public static T GetDefault () { return (T) GetDefault(typeof(T)); } /// /// [ /// The Type for which to get the default value ///public static object GetDefault(Type type) ] ////// Retrieves the default value for a given Type /// The default value for ////// 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. /// ///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"); }
GetDefault的第一个(通用)版本当然是C#的冗余版本,因为您可能只使用默认(T)关键字.
请享用!