c# - 代码在监视窗口中工作,但在代码执行期间无法转换对象
问题描述
我的.NET 4.7.2
服务器应用程序中有这些代码行:
object saveObject = proxyDef.GetEntityAsNativeObject(entity, DynamicProxyAssembly); // this works
((AxdSalesOrder)saveObject).SalesTable[0].TableDlvAddr = null; // this throws error
我可以在中执行空集(上面的第 2 行),VS2019 Watch Window
它可以完美地工作并达到预期的效果。但是当我允许它在正常执行中运行时(无论是否在调试模式下),我在第二行得到一个未处理的异常:
无法将“AxdSalesOrder”类型的对象转换为“Elogix.MSAx.Core.Ax2012ElogixServices.AxdSalesOrder”类型
有与该类型相关的动态内容:
public override object GetEntityAsNativeObject(MSAxEntity entity, Assembly dynamicProxyAssembly) {
var salesOrderObject = Activator.CreateInstance(dynamicProxyAssembly.GetType("AxdSalesOrder"));
var salesOrderTable = DynamicEntityUtil.CreateObjectFromDynamicEntity(entity, dynamicProxyAssembly, "AxdEntity_SalesTable");
Array tableLines =
Array.CreateInstance(
salesOrderObject.GetType().GetProperty("SalesTable").PropertyType.GetElementType(), 1);
tableLines.SetValue(salesOrderTable, 0);
salesOrderObject.SetPropertyValue("SalesTable", tableLines);
return salesOrderObject;
}
public static object CreateObjectFromDynamicEntity(DynamicEntity entity, Assembly dynamicProxyAssembly, string objectTypeName) {
return CreateObjectFromDynamicEntity(entity, dynamicProxyAssembly.GetType(objectTypeName));
}
public static object CreateObjectFromDynamicEntity(DynamicEntity entity, Type type) {
if (type == null) {
throw new ArgumentException("Cannot create object from dynamic entity because \"Type\" is null.");
}
if (type.IsArray) {
return CreateArrayFromDynamicEntity(entity, type);
}
return CreateClassFromDynamicEntity(entity, type);
}
private static object CreateClassFromDynamicEntity(DynamicEntity entity, Type type) {
var nativeObject = Activator.CreateInstance(type);
// this will recursively convert the dynamic values to the native type values on the object.
updateValuesFromDynamicValues(entity);
var modifiedProperties = from property in entity.Properties
//where property.State != DynamicPropertyState.Unchanged
select property;
foreach(var property in modifiedProperties) {
Type valueUnderlyingType = Nullable.GetUnderlyingType(property.Type);
if (valueUnderlyingType != null && valueUnderlyingType.IsEnum) {
PropertyInfo info = nativeObject.GetType().GetProperty(property.Name);
Type targetUnderlyingType = Nullable.GetUnderlyingType(info.PropertyType);
if (property.Value == null) {
info.SetValue(nativeObject, null, null);
} else {
object correctedValue = property.Value.CorrectedEnumValue(targetUnderlyingType);
info.SetValue(nativeObject, correctedValue, null);
}
} else if (property.Type.IsEnum) {
if (property.Value == null) {
continue;
}
object correctedValue = property.Value.CorrectedEnumValue(property.Type);
nativeObject.SetPropertyValue(property.Name, correctedValue);
} else {
try {
nativeObject.SetPropertyValue(property.Name, property.Value);
} catch (Exception ex) {
Log.Write(ex.Message);
}
}
}
return nativeObject;
}
这是它在 VS2019 中的外观Watch Window
:
这样做Immediate Window
:
var t = saveObject.GetType();
t.FullName
"AxdSalesOrder"
正如你所看到的,由于类型的FullName
动态特性,类型不是很完整,没有任何限制。
我可以这样尝试:
(saveObject as AxdSalesOrder).SalesTable[0].TableDlvAddr = null;
同样,这在 Watch 中有效,但在正常执行时抛出此异常:
你调用的对象是空的。
显然,VS/Watch知道 type,这就是为什么它可以在 Watch 内部执行而不会出错。但是.net 运行时显然不知道运行时的类型。我怎样才能让这个对象在正常的代码执行中像在 Watch 中运行一样工作?
解决方案
这里的答案是利用动态类型,因为这里没有静态类型:
dynamic saveObject = proxyDef.GetEntityAsNativeObject(entity, DynamicProxyAssembly);
saveObject.SalesTable[0].TableDlvAddr = null;
另一种可能的方法是使用反射,但是由于应用于对象的表达式涉及两个属性和一个索引查找 ( .SalesTable[0].TableDlvAddr
),这看起来可读性要差得多。
GetEntityAsNativeObject
也可以从这种风格中受益,您可以考虑将其重写为使用动态绑定而不是反射。
推荐阅读
- json - Camel DataFormat Jackson 使用蓝图 XML DSL 引发上下文异常
- jquery - 每隔一周将 JQuery datepicker 限制为 1(每两周一次)
- java - 生成带有 minifyEnabled 设置为 true 的签名 APK 后,firebase UI 输出空白
- python - 使用 Keras 进行图像分类:“预期activation_1 具有形状 (2,) 但得到的数组具有 (1,)”
- mockito - PowerMockito 链接对于 Spied 类不能可靠地工作
- python - 在python中使用整数元组作为键不起作用
- xcode - 您可以/应该在 Xcode 的 xcassets 中存储多少图像?
- unity3d - 我受到伤害但我看不到动画
- python - ValueError: Traceback(最近一次调用最后一次)
在 () - c++ - 如何动态跟踪OpenGL中的纹理单元?