У меня есть некоторый. 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 поставляется из JCL в проекте JEDI, здесь:
https://github.com/project-jedi/jcl/blob/master/jcl/source/windows/mscorlib_TLB.pas
Ошибка возникает при вызове LPropertyInfo.SetValue в TDotNetObject.SetProperty:
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]''.
Свойство DefectStatus объекта C# объявляется как:
public DefectStatus? Status
( т. е. обнуляется)
Объявлен тип свойства Status в C#:
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# здесь:
{ ссылка }
Однако я немного растерялся относительно того, как сделать то же самое в 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;
Цель этого фрагмента кода - просто вызвать метод ToObject типа Enum. Получение LType и LDefectStatusType завершается успешно, однако вызов InvokeMember_2 этого не делает, с кодом возврата: 0x80131512, который, по-видимому, является исключением пропавшего члена. Есть идеи, что я делаю не так?