我的.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
也可以从这种风格中获益,你可以考虑重写使用动态绑定,而不是反射。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句