我有一些.NET互操作代码,可以在其中加载对象并读取属性,但是在对象上设置属性时遇到了麻烦。这是Delphi代码的相关部分:
uses
mscorlib_TLB, Winapi.ActiveX;
type
// Irrelevant parts of the code omitted
TDotNetObject = class(TObject)
private
FTarget: OleVariant;
FType: _Type;
public
procedure SetProperty(const APropertyName: string; const AValue: OleVariant; const AIndex: Integer = -1);
end;
function VariantToPSafeArray(const AValue: Variant): PSafeArray;
begin
Result := PSafeArray(VarArrayAsPSafeArray(AValue));
end;
procedure TDotNetObject.SetProperty(const APropertyName: string; const AValue: OleVariant; const AIndex: Integer = -1);
var
LPropertyInfo: _PropertyInfo;
LIndex: PSafeArray;
begin
if AIndex >= 0 then
LIndex := VariantToPSafeArray(VarArrayOf([AIndex]))
else
LIndex := nil;
LPropertyInfo := FType.GetProperty(APropertyName, BindingFlags_Instance or BindingFlags_Public or BindingFlags_NonPublic);
if LPropertyInfo <> nil then
LPropertyInfo.SetValue(FTarget, AValue, LIndex);
end;
procedure UpdateDefectStatus(const ADefectID, AStatus: Integer);
var
LObject: TDotNetObject;
begin
// ** Code to obtain the object omitted ***
LObject.SetProperty('Status', AStatus);
end;
mscorlib_TLB单元来自Project JEDI中的JCL,在这里:
https://github.com/project-jedi/jcl/blob/master/jcl/source/windows/mscorlib_TLB.pas
在TDotNetObject.SetProperty中调用LPropertyInfo.SetValue时引发错误:
Project TestProject.exe raised exception class EOleException with message 'Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1[MTData.Transport.Tracking.DefectReporting.DefectStatus]''.
C#对象上的DefectStatus属性声明为:
public DefectStatus? Status
(即它可以为空)
C#中的Status属性类型声明为:
public enum DefectStatus
{
/// <summary>
/// Defect Reported.
/// </summary>
Reported,
/// <summary>
/// Defect assessed.
/// </summary>
Assessed,
/// <summary>
/// Defect on work order.
/// </summary>
OnWorkOrder,
/// <summary>
/// Defect closed.
/// </summary>
Closed
}
我在这里找到了如何使用C#处理这种情况的解决方案:
https://stackoverflow.com/a/13270302/3164070
但是我对如何在Delphi中执行相同操作感到迷茫。有任何想法吗?
编辑
鉴于奥利维尔的回答,我试图编写一些Delphi代码来做等效的操作,如下所示:
procedure InvokeToObject;
var
LType, LDefectStatusType: _Type;
LInvokeFlags: TOleEnum;
LArgs: PSafeArray;
LValue: Integer;
LResult: OleVariant;
LRes: HRESULT;
LResHex: string;
begin
LType := MTDataClr.GetCoreType('System.Enum');
LDefectStatusType := MTDataClr.GetType('MTData.Transport.Tracking.DefectReporting.DefectStatus');
LInvokeFlags := BindingFlags_InvokeMethod or BindingFlags_Static;
LValue := 1;
LArgs := VariantToPSafeArray(VarArrayOf([LDefectStatusType, LValue]));
LRes := LType.InvokeMember_2('ToObject', LInvokeFlags, nil, Null, LArgs, nil, LResult);
LResHex := IntToHex(LRes);
end;
这段代码的目标只是调用Enum类型的ToObject方法。成功获取LType和LDefectStatusType,但是对InvokeMember_2的调用未成功,返回码为:0x80131512,这显然是Missing Member异常。关于我在做什么错的任何想法吗?
参考方案
问题在于枚举不是int,这意味着SetValue()
需要执行两次转换(Int32
到DefectStatus
和DefectStatus
到DefectStatus?
),而不能(只能执行一个) )。
这是一个C#代码,可重现您要执行的操作:
using System;
using System.Reflection;
public enum DefectStatus
{
Reported,
Assessed,
OnWorkOrder,
Closed
}
public class Defect
{
public DefectStatus? Status {get; set;}
}
public class Test
{
public static void Main()
{
Defect def = new Defect();
PropertyInfo pi = typeof(Defect).GetProperty("Status");
// This throws an ArgumentException
// pi.SetValue(def, 1, null);
// Retrieve the Assessed enum via its numeric value
object assessed = Enum.ToObject(typeof(DefectStatus), 1);
// This works as expected
pi.SetValue(def, assessed, null);
Console.WriteLine(def.Status);
}
}
因此,您需要在Delphi中检索枚举。为此,您将需要使用API来访问Enum
类型并对其调用ToObject
。
我正在将一个较旧的小型mvc5应用程序移植到.Net Core 2.0和MVC 6,更多地是作为练习来学习如何做。在该应用程序中,我有一个Base Controller类,其主要工作是确保布局模型中包含用户的配置文件对象。 protected override void OnActionExecuted(ActionExecutedContext filte…
在.NET中导入模块,然后将其用作对象? - c#我有一个Python模块,我希望能够像C#中的类一样导入它的一部分,并尽可能地访问其方法,例如.NET native。如何使用IronPython完成此操作? 参考方案 看一下这个:https://wiki.python.org/moin/IntegratingPythonWithOtherLa…
在.NET和Python中\ Q \ E是否等效? - c#PHP && Java正则表达式可让您像这样在\Q和\E之间转义部分正则表达式\d+\Q**(+)**\E\d+ 例如12**(+)**22的此匹配项这很方便,因为没有它,您就必须逃脱特殊字符\d+\*\*\(\+\)\*\*\d+ .NET中有类似的东西吗?关于Python也有同样的问题谢谢 参考方案 Python不支持\Q \E。您可以使…
解决编译器错误CS1519:类,结构或接口成员声明中的无效令牌',' - c#我正在使用Web应用程序项目文件的ASP .NET 2.0站点上工作,因此可以编译为dll,而不是像处理较旧样式的Web站点项目一样部署源代码。该站点在网站的根目录中运行时,在我的测试服务器(Windows Server 2003 R2,IIS6)上可以正常运行。但是,我需要在虚拟目录下运行它。切换到该页面时,浏览到站点中的任何页面时都会收到以下错误CS15…
将字符串分配给numpy.zeros数组[重复] - pythonThis question already has answers here: Weird behaviour initializing a numpy array of string data (4个答案) …