c# – 检查PropertyInfo.SetValue是否会抛出ArgumentException

c# – 检查PropertyInfo.SetValue是否会抛出ArgumentException,第1张

概述我继承了一些尝试设置属性的代码: object target = ... // some instance on which we want to set a propertyobject value = ... // some value - in this case, a stringvar propertyInfo = ... // some property of tar 我继承了一些尝试设置属性的代码:
object target = ...    // some instance on which we want to set a propertyobject value = ...     // some value - in this case,a stringvar propertyInfo = ... // some property of target - in this case,not a stringtry{    propertyInfo.SetValue(obj,value,null);}catch (ArgumentException){    // We go off and look for our own way of converting between    // the type of value and the type of the property.}

在当前使用中,异常被捕获并抛出很多,所以我想首先进行检查

if (propertyInfo.PropertyType.IsAssignableFrom(value.GetType()){    // Try/catch as above}else{    // Do the manual conversion as if the exception had been thrown.}

这运行得更快.但是,我唯一担心的是,IsAssignableFrom可能会为某些类型返回false,而SetValue实际上会成功. (这会导致我们在不需要时查找手动转换,并且可能无法完全设置值.)

SetValue的规范说

value cannot be converted to the type of PropertyType

这与可分配性不完全相同.

(如果在SetValue失败的情况下IsAssignableFrom返回true,那很好 – 手动转换仍然会发生.)

有人可以向我确认这是否可行?

解决方法 正如您所怀疑的那样,short类型的值可以通过反射分配给int类型的属性,尽管typeof(int).IsAssignableFrom(typeof(short))返回false.

查看ArgumentException的stacktrace:

at System.RuntimeType.TryChangeType(Object value,Binder binder,CultureInfo culture,Boolean needsspecialCast)  at System.RuntimeType.CheckValue(Object value,BindingFlags invokeAttr)  at System.Reflection.MethodBase.CheckArguments(Object[] parameters,BindingFlags invokeAttr,Signature sig)  at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj,Object[] parameters,CultureInfo culture)  at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,CultureInfo culture)  at System.Reflection.RuntimePropertyInfo.SetValue(Object obj,Object value,Object[] index,Object[] index)  at System.Reflection.PropertyInfo.SetValue(Object obj,Object value)  at ConsoleApplication3.Program.Main(String[] args) in ...

RuntimeType.TryChangeType中抛出异常.查看mscorlib中的源代码:

// System.RuntimeType[SecurityCritical]private object TryChangeType(object value,bool needsspecialCast){    ...    if (this.isinstanceOfType(value))    {      return value;    }    ...      if (RuntimeType.CanValueSpecialCast(valueType,this))      {    ...  }  throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture,Environment.GetResourceString("Arg_ObjObjEx"),value.GetType(),this));}

不幸的是,有很多内部函数被调用来确定是否应该抛出ArgumentException.我怀疑原语的转换是在这个函数周围处理的:

// System.RuntimeType[SecurityCritical][MethodImpl(MethodImplOptions.InternalCall)]private static extern bool CanValueSpecialCast(RuntimeType valueType,RuntimeType targettype);

System.RuntimeType.CheckValue(object,Binder,CultureInfo,BindingFlags)中也有一些有趣的代码:

bool flag = base.IsPointer || this.IsEnum || base.IsPrimitive;if (flag){  ...  if (RuntimeType.CanValueSpecialCast(valueType,this))  {    ...  }}

所以它看起来像指针,枚举和原始类型以不同的方式处理.我不鼓励你试着复制那个逻辑.使用IsAssignableFrom可能更容易,并分别处理整数类型.处理指针,枚举和原始类型参数看起来非常复杂,我会回避尝试捕获那里.但是,如果发生参数错误,则可以缓存,因此对具有相同参数类型的同一方法的后续调用可能会更快一些.

总结

以上是内存溢出为你收集整理的c# – 检查PropertyInfo.SetValue是否会抛出ArgumentException全部内容,希望文章能够帮你解决c# – 检查PropertyInfo.SetValue是否会抛出ArgumentException所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1243496.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存