Dave Nottage 557 Posted April 7, 2020 I have some .NET interop code where I've managed to load objects and read properties, however I am having trouble with setting a property on an object. Here's the relevant parts of the Delphi code: 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; An error is thrown when LPropertyInfo.SetValue is called in TDotNetObject.SetProperty: The Status property type in C# is declared: 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 } I found a solution for how to handle this situation using C# here:https://stackoverflow.com/a/13270302/3164070 However I'm a bit lost as to how to do the same in Delphi. Any ideas? Share this post Link to post
Lars Fosdal 1792 Posted April 7, 2020 100% guesswork without any foundation, except name likeness, follows: There is a GetUnderlyingType property in System.RTTI type TRttiEnumerationType - but it is used absolutely nowhere in the RTL. Also, WinAPI.Ole2 contains a VariantChangeType, and WinAPI.ActiveX contains a VariantChangeTypeEx that may be relevant. System.VarUtils contain both. function TRttiEnumerationType.GetUnderlyingType: TRttiType; begin Result := Pool.TypeOrNil(TypeData^.BaseType); end; function TRttiPool.TypeOrNil(Value: PPTypeInfo): TRttiType; begin if Value = nil then Exit(nil); Result := GetType(Value^); end; function TRttiPool.GetType(ATypeInfo: Pointer): TRttiType; begin if ATypeInfo = nil then Exit(nil); Result := TRttiType(ReadObjectPointer(TRttiType, nil, ATypeInfo)); end; Share this post Link to post
Guest Posted April 7, 2020 The problem, I think, is that .NET's Nullable is a generic type and as such can't be exposed to COM. Share this post Link to post
Lars Fosdal 1792 Posted April 7, 2020 But isn't it still a value type? https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types#how-to-identify-a-nullable-value-type Share this post Link to post
Dave Nottage 557 Posted April 23, 2020 I've posted a question about this on SO which has received some attention: https://stackoverflow.com/questions/61334031/setting-a-nullable-property-on-a-net-object ..and I think I may be closer to a solution. Can someone check the code for the InvokeToObject method to see if I'm missing anything critical? Share this post Link to post
Dave Nottage 557 Posted April 30, 2020 I've posted a new question after help from Olivier: https://stackoverflow.com/questions/61514990/setting-an-enum-property-on-a-net-object If anyone can help, it would be greatly appreciated. 1 Share this post Link to post