Why the wsdl importer generates strange objects? - wcf

I created a web service in .NET, that works fine on Silverlight and WPF. I want to do some try with Delphi XE4. My service is exposed with SOAP, so it's perfect for Rad Studio that have a automatic WSDL importer. My problem is that each type of my ws is represented with 2 classes.
the first is a complex type, which inherits from TRemotable:
// ************************************************************************ //
// XML : MessageRecuperationSalaries, global, <complexType>
// Espace de nommage : http://XXX/XXX/XXX
// ************************************************************************ //
MessageRecuperationSalaries2 = class(TRemotable)
private
FEtabCode: string;
FEtabCode_Specified: boolean;
FSalaries: ArrayOfSalarie;
FSalaries_Specified: boolean;
procedure SetEtabCode(Index: Integer; const Astring: string);
function EtabCode_Specified(Index: Integer): boolean;
procedure SetSalaries(Index: Integer; const AArrayOfSalarie: ArrayOfSalarie);
function Salaries_Specified(Index: Integer): boolean;
public
destructor Destroy; override;
published
property EtabCode: string Index (IS_OPTN or IS_NLBL) read FEtabCode write SetEtabCode stored EtabCode_Specified;
property Salaries: ArrayOfSalarie Index (IS_OPTN or IS_NLBL) read FSalaries write SetSalaries stored Salaries_Specified;
end;
The second class inherits from the first one and doesn't contain any property:
// ************************************************************************ //
// XML : MessageRecuperationSalaries, global, <element>
// Espace de nommage : http://XXX/XXX/XXX
// ************************************************************************ //
MessageRecuperationSalaries = class(MessageRecuperationSalaries2)
private
published
end;
Is there any option to directly generate only one class per type that inherits from TRemotable ? Or is my web service in cause ?

Related

Why do constructors have to have a public and not internal visibility?

Only initializes the contract, and I don't understand why it is not an internal function. With this, is more cheap the cost of the gas insted implementing a public function
API from Solidity :
// This is the constructor which registers the
// creator and the assigned name.
constructor(bytes32 _name) public {
// State variables are accessed via their name
// and not via e.g. `this.owner`. Functions can
// be accessed directly or through `this.f`,
// but the latter provides an external view
// to the function. Especially in the constructor,
// you should not access functions externally,
// because the function does not exist yet.
// See the next section for details.
owner = msg.sender;
// We do an explicit type conversion from `address`
// to `TokenCreator` and assume that the type of
// the calling contract is `TokenCreator`, there is
// no real way to check that.
creator = TokenCreator(msg.sender);
name = _name;
}

What interface to I need to implement to allow ForEach in VBA on a COM object written in delphi?

Imagine I want to do something like this in VBA (pseudocode), and assuming my has an enumerable property IDList:
Dim MyObject object
set MyObject= CreateObject("MyObjectClass")
for each Item as integer in MyObject.IDList
Debug.Write(Cstr(Item) & ";")
Next
What would my property IDList have to look like in Delphi?
Simply deriving it from IEnumerable<integer> or IEnumerable does not seem to do the job.
Base code
In order to avoid trouble with the default IENum and IEnum<T> interfaces I have created my own set of interfaces for enumeration on the Delphi side, to be used in object pascal for .. in .. loops.
ISGEnumeratorBase= interface(IInterface)
['{DA91A203-3B39-4287-9A6F-6E9E4B184BAD}']
function MoveNext: Boolean;
end;
ISGEnumeratorReset = interface (ISGEnumeratorBase)
['{FBD2EFBD-D391-4BE2-A3AB-9C9D09197F78}']
procedure Reset;
end;
ISGEnumeratorClone = interface (ISGEnumeratorBase)
['{E3A128FD-7495-464D-BD5E-3EBA3AEFE94F}']
function Clone:ISGEnumeratorBase;
end;
/// <summary>
/// <para>
/// Required for implementing for..in loops
/// </para>
/// An alternative generic interface for the IEnumerator<T> defined
/// in the system unit. Allows for easier implementation of enumerators for
/// interfaced classes etc.
/// </summary>
ISGEnumerator<T> = interface(ISGEnumeratorBase)
function GetCurrent:T;
property Current: T read GetCurrent;
end;
/// <summary>
/// <para>
/// Required for implementing for..in loops
/// </para>
/// <para>
/// An alternative generic interface for the IEnumerator<T>
/// defined in the system unit. Allows for easier implementation of
/// enumerators for interfaced classes etc. <br />
/// </para>
/// </summary>
ISGEnumerable<T>=interface(IInterface)
function GetEnumerator:ISGEnumerator<T>;
end;
So the enumerators I use in my application use these interfaces to "publish" themselves.
What I want is to have an adapter class that allows for creating the IEnumVariant interface on may ISGEnumerator<T> and ISGEnumerable<T> interfaces
Summary
I have created a generic interface adapter that allows for more or less easy implementation of the IEnumVariant interface. I also discovered that the IEnumVariant interface is defined in the ActiveX unit provided with Delphi, and that it uses stdole32.tpl as a type library.
OLE enumerator base classes
Here are the enumerator base and the generic enumerator base classes:
type
TSGOLEVariantEnumeratorAdapterBase=class (TAutoIntfObject,IEnumVariant)
private class var
vOLETypeLib:ITypeLib;
private
class function GetOLETypeLib: ITypeLib; static;
class Destructor ClassDestroy;
// for IOLEEnumVariant
function Next(celt: LongWord; var rgvar: OleVariant; out pceltFetched: Longword): HResult; stdcall;
function Skip(celt: LongWord): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out Enum: IEnumVariant): HResult; stdcall;
protected
class property OLETypeLib:ITypeLib read GetOLETypeLib;
function DoNext(aFetchRequestCount: LongWord; var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean; virtual; abstract;
function DoSkip(aSkipCOunt: LongWord): boolean; virtual; abstract;
function DoReset: boolean; virtual;
function DoClone(out Enum: IEnumVariant): boolean; virtual;
public
constructor Create;
end;
TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>=class (TSGOLEVariantEnumeratorAdapterBase,ISGEnumerator<TEnumeratedType>)
private
FSourceEnumerator:ISGEnumerator<TEnumeratedType>;
protected
function MapCurrentToVariant(aCurrent:TEnumeratedType):olevariant; virtual;
function DoReset: boolean; override;
function DoClone(out Enum: IEnumVariant): boolean; override;
function DoNext(aFetchRequestCount: LongWord; var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean; override;
function DoSkip(aSkipCOunt: LongWord): boolean; override;
property SourceEnumerator:ISGEnumerator<TEnumeratedType> read FSourceEnumerator implements ISGEnumerator<TEnumeratedType>;
public
constructor Create(const aSourceEnumerator:ISGEnumerator<TEnumeratedType>);
end;
I struggled with the instantiation TAutoIntfObject base class and the correct type libraries, but I finally managed to work it out like below. I use a class var for the type library to avoid loading it over and over again.
constructor TSGOLEVariantEnumeratorAdapterBase.Create;
begin
inherited Create(OLETypeLib,IEnumVariant);
end;
class destructor TSGOLEVariantEnumeratorAdapterBase.ClassDestroy;
begin
vOLETypeLib:=nil;
end;
class function TSGOLEVariantEnumeratorAdapterBase.GetOLETypeLib: ITypeLib;
begin
// HH we cannot lose Win.ComServ in a package
// thats why I cloned the call or LoadTypeLibrary here
if not Assigned(vOLETypeLib) then
OleCheck(LoadTypeLibEx('stdole32.tlb', REGKIND_NONE, vOLETypeLib));
Result:=vOLETypeLib;
end;
After that I implemented the interface's methods, also allowing for exceptions to be handled correctly for the dispintf. The actual "meat" of the loop implementation are put in virtual methods called from the interface methods. The interface methods look like this:
function TSGOLEVariantEnumeratorAdapterBase.Next(celt: LongWord; var rgvar: OleVariant;
out pceltFetched: Longword): HResult;
VAR lActuallyFetched:longword;
begin
lActuallyFetched:=0;
try
if DoNext(celt,rgvar,lActuallyFetched) then
Result:=S_OK
else Result:=S_FALSE;
if Assigned(#pceltFetched) then
pceltFetched:=lActuallyFetched;
except
Result:=SafeCallException(ExceptObject,ExceptAddr);
end;
end;
function TSGOLEVariantEnumeratorAdapterBase.Skip(celt: LongWord): HResult;
begin
try
if DoSkip(celt) then
Result:=S_OK
else Result:=S_FALSE;
except
Result:=SafeCallException(ExceptObject,ExceptAddr);
end;
end;
function TSGOLEVariantEnumeratorAdapterBase.Reset: HResult;
begin
try
if DoReset then
Result:=S_OK
else Result:=S_FALSE;
except
Result:=SafeCallException(ExceptObject,ExceptAddr);
end;
end;
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.DoClone(out Enum: IEnumVariant): boolean;
VAR lCloneIntf:ISGEnumeratorClone;
lCLonedEnumerator:ISGEnumerator<TEnumeratedType>;
begin
if Supports(FSourceEnumerator,ISGEnumeratorClone,lCloneIntf) then
begin
lCLonedEnumerator:=ISGEnumerator<TEnumeratedType>(lCloneIntf.Clone);
Enum:=TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>(self.ClassType).Create(lCLonedEnumerator);
Result:=True;
end
else Result :=inherited;
end;
function TSGOLEVariantEnumeratorAdapterBase.Clone(out Enum: IEnumVariant): HResult;
begin
try
if DoClone(Enum) then
Result:=S_OK
else Result:=S_FALSE;
except
Result:=SafeCallException(ExceptObject,ExceptAddr);
end;
end;
Clone and Reset
I have added virtual methods for the Clone and Reset methods, but these are actually not called from within Excel VBA in my example,
Generic IEnumVariant adapter class
The next thing was to create the Generic adapter which overrides the Doxxx methods and adds a MapCurrentToVariant routine to get the 'Current' value from the source enumerator to the output variant. This routine is virtual so it can be overridden for special or more efficient transformations.
Thus the generic class looks like this:
TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>=class (TSGOLEVariantEnumeratorAdapterBase,ISGEnumerator<TEnumeratedType>)
private
FSourceEnumerator:ISGEnumerator<TEnumeratedType>;
protected
function MapCurrentToVariant(aCurrent:TEnumeratedType):olevariant; virtual;
function DoReset: boolean; override;
function DoClone(out Enum: IEnumVariant): boolean; override;
function DoNext(aFetchRequestCount: LongWord; var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean; override;
function DoSkip(aSkipCOunt: LongWord): boolean; override;
property SourceEnumerator:ISGEnumerator<TEnumeratedType> read FSourceEnumerator implements ISGEnumerator<TEnumeratedType>;
public
constructor Create(const aSourceEnumerator:ISGEnumerator<TEnumeratedType>);
end;
Implementing the overridden routines was pretty straightforward.
constructor TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.Create(
const aSourceEnumerator: ISGEnumerator<TEnumeratedType>);
begin
FSourceEnumerator:=aSourceEnumerator;
inherited Create;
end;
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.MapCurrentToVariant(aCurrent: TEnumeratedType): olevariant;
begin
Result:=TValue.From<TEnumeratedType>(aCurrent).AsVariant;
end;
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.DoNext(aFetchRequestCount: LongWord;
var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean;
type
TVariantList=array[0..0] of Olevariant;
begin
aActuallyFetchedCount:=0;
while (aFetchRequestCount>0) and SourceEnumerator.MoveNext do
begin
dec(aFetchRequestCount);
TVariantList(rgvar)[aActuallyFetchedCount]:=MapCurrentToVariant(SourceEnumerator.Current);
inc(aActuallyFetchedCount);
end;
Result:=(aFetchRequestCount=0);
end;
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.DoSkip(aSkipCOunt: LongWord): boolean;
begin
while (aSkipCount>0) and SourceEnumerator.MoveNext do
dec(aSkipCount);
Result:=(aSkipCOunt=0);
end;
I have added the Clone and Reset options later on, as they are not actually used by my application, so maybe for future usage. The implementations look like this:
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.DoClone(out Enum: IEnumVariant): boolean;
VAR lCloneIntf:ISGEnumeratorClone;
lCLonedEnumerator:ISGEnumerator<TEnumeratedType>;
begin
if Supports(FSourceEnumerator,ISGEnumeratorClone,lCloneIntf) then
begin
lCLonedEnumerator:=ISGEnumerator<TEnumeratedType>(lCloneIntf.Clone);
Enum:=TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>(self.ClassType).Create(lCLonedEnumerator);
Result:=True;
end
else Result :=inherited;
end;
function TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.DoReset: boolean;
VAR lResetIntf:ISGEnumeratorReset;
begin
if Supports(FSourceEnumerator,ISGEnumeratorReset,lResetIntf) then
begin
lResetIntf.Reset;
Result:=True;
end
else Result := inherited;
end;
Finally, I decided to create an enumerable adapter class as well which may come in handy in some cases:
TSGGenericOLEVariantEnumerableAdapter<TEnumeratedType>=class (TAutoIntfObject,ISGEnumerable<TEnumeratedType>)
private
FSourceEnumerable:ISGEnumerable<TEnumeratedType>;
protected
function Get__NewEnum: IUnknown; safecall; inline;
property SourceEnumerable:ISGEnumerable<TEnumeratedType> read FSourceEnumerable implements ISGEnumerable<TEnumeratedType>;
public
constructor Create(const aTypeLib:ITypeLib;const aDispIntf:TGUID;const aSourceEnumerable:ISGEnumerable<TEnumeratedType>);
end;
The implementation of the class:
constructor TSGGenericOLEVariantEnumerableAdapter<TEnumeratedType>.Create(const aTypeLib:ITypeLib;const aDispIntf:TGUID;const aSourceEnumerable:ISGEnumerable<TEnumeratedType>);
begin
FSourceEnumerable:=aSourceEnumerable;
inherited Create(aTypeLib,aDispIntf);
end;
function TSGGenericOLEVariantEnumerableAdapter<TEnumeratedType>.Get__NewEnum: IUnknown;
begin
Result:=TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType>.Create(SourceEnumerable.GetEnumerator);
end;
At the spots where I plan to use my code, everything looks rather clean, and only little has to be implemented. Below is an example of the enumerator to get a bunch of object IDs from my actual application model:
TAMDBObjIDEnumeratorAdapter=class (TSGGenericOLEVariantEnumeratorAdapter<integer>);
TAMDBObjIDEnumerableAdapter=class (TSGGenericOLEVariantEnumerableAdapter<integer>,IAMObjectIDs,ISGEnumerable<integer>)
public
constructor Create(const aSourceEnumerable:ISGEnumerable<integer>);
end;
....
constructor TAMDBObjIDEnumerableAdapter.Create(const aSourceEnumerable: ISGEnumerable<integer>);
begin
inherited Create(comserver.TypeLib,IAMObjectIDs,aSOurceEnumerable);
end;
The code has actually been tested using Excel and Delphi, but providing all the code with my internal solutions for the Delphi enumerators is way beyond the topic of this issue, that;s why I did not create a demo project for this. Who knows, if I find the time and enough upvotes/requests I may put some more energy in this.
I hope my journey into finding a "working and clean" solution for this in Delphi will help others.

Method's type signature is not PInvoke compatible

I'm new to vb.net and trying to call Delphi Dll that returns a record. If I put three integers in struct it works when I try something like the following code I get "Method's type signature is not PInvoke compatible".. Any ideas off why I cant add Byte Array or even if I add boolean it fails.
Public Structure SysInfo
Public iPrtRes As Integer
Public iMaxRips As Integer
Public iUnits As Integer
Public str As Byte()
End Structure
<DllImport("C:\project2.DLL", CallingConvention:=CallingConvention.Cdecl)>
Public Function getsysinfoF() As SysInfo
End Function
Dim theSysInfoRec As SysInfo
ReDim theSysInfoRec.str(255)
theSysInfoRec = getsysinfoF()
Delphi
type
SysInfo = record
iPrtRes: Integer;
iMaxRips: Integer;
iUnits: Integer;
str: array[0..255] of Byte;
end;
function getsysinfoF() : SysInfo; cDecl
begin
result.iPrtRes := 400;
result.iMaxRips := 300;
result.iUnits := 200;
result.str[0] := $ff;
end;
Found solultion in
Passing record as a function result from Delphi DLL to C++
.NET managed arrays are different from unmanaged arrays in other lanuages. You need to tell PInvoke how to marshal the array field of the struct, and that depends on how the DLL allocates and manages that array in the first place. Is it a C-style array? A Delphi-style dynamic array? An ActiveX/COM SafeArray? That kind of information needs to be included in the PInvoke declaration of the struct on the .NET side using the MarshalAs attribute (obviously, Delphi-style dynamic arrays are not supported by .NET).
Refer to MSND for more details:
Default Marshaling for Arrays
MarshalAsAttribute Class
Update: For example:
Delphi:
type
SysInfo = record
iPrtRes: Integer;
iMaxRips: Integer;
iUnits: Integer;
str: array[0..255] of Byte;
end;
.NET:
Public Structure <StructLayout(LayoutKind.Sequential)> SysInfo
Public iPrtRes As Integer
Public iMaxRips As Integer
Public iUnits As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst := 256)>
Public str() As Byte
End Structure

ActionScript Class Number Communication

I'm a little new to AS3, but I have a question.
I have a variable called "lives". It is a Number. I also have a class. It is called "Enemy". Within the "Enemy" class, there is a function called "collision_detection". How can I change the value of "lives" from "collision_detection"? Thank you!
EDIT:
I have an Enemy class. I need to communicate from within the class to let the main program know that a collision occurred. How can I send this message to the main program?
EDIT II:
Here is the collision function :
public class Enemy extends MovieClip {
private var hoster : MovieClip;
private var life: Number;
public function temp_bad_thing(host : MovieClip , lives : Number) {
this.addEventListener(Event.ENTER_FRAME , check_collision);
hoster = host;
life = lives;
this.y = 0;
this.x = Math.floor(Math.random()*(551));
}
private function check_collision (evt:Event) : void{
if(this.hitTestObject(hoster) == true){
trace('COLLISION');
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME , check_collision);
}
}
}
Now how can I get this class to change the value of a variable in my main flash file?
If the variable is declared in the same package and not in another class you should be able to assign to it without doing anything special.
If it's in another class then declare the lives variable as static public var lives: Number. This way you can assign to the variable using otherClass.lives. Only one copy of static variable will exist regardless of how many objects you make.

Static or Class Method in Delphi Prism

I am working with Delphi Prism for .NET. I need to call a public method in my mainform class from another winform method. So, having recently learned about static, I used it in my program. Static or Class winform works great, but making a method static or class doesn't seem to work the same.
I have a method called updateButtons in my mainform class. It updates all the buttons and controls on the mainform according to the user's action. This method needs to be called from another winform method. So, I made that UpdateButtons method into static or class. Although now I see the method to call, compiler doesn't like. It keeps raising the following error, "Cannot call instance member (Any controls) without an instance reference."
How can you make a method a class or static and still have access to controls from the winform?
Main class with static or class method:
MainForm = partial class(System.Windows.Forms.Form)
private
protected
method Dispose(disposing: Boolean); override;
public
class method updateButtons;
end;
definition of updatebutton:
class method MainForm.updateButtons;
begin
if SecurityEnabled then
LoginBtn.Enabled := true //All the lines where I call Buttons raise the error exception that I mentioned above.
else
begin
UnitBtn.Enabled := true;
SignalBtn.Enabled := true;
AlarmBtn.Enabled := true;
MakerBtn.Enabled := true;
TrendBtn.Enabled := true;
DxCommBtn.Enabled := (Scanning = false);
TxBtn.Enabled := true;
ControlBtn.Enabled := true;
PIDBtn.Enabled := true;
SystemBtn.Enabled := true;
WinListBox.Enabled := true;
WinBtn.Enabled := true;
ShutdownBtn.Enabled := true;
OptionBtn.Enabled := true;
LoginBtn.Enabled:=false;
end;
end;
This cannot work in the way you want it to work.
A class (or static) method is called statically on the class, opposed to be called on a specific object instance.
You can instanciate the same form class several times. Then you have several object instances of the form, which can be opened or hidden all at the same time.
Now, when you call the static method, WHICH of those several forms should be updated? The compiler cannot tell, and can't allow access to fields or properties belonging to the object's instances.
For this to work, you must make the method a normal method of the object (non-class or static) and you need to retrieve a reference of the concrete form object instance and call it there.
Since the method I want to execute is from MainForm Window Form and fired from within a button event, I decided to call that method from within the Button Click event from MainForm instead of from other winform. This has the same end result. Plus, it is simpler.
//This is just a sample code
MainForm = class(system.windows.forms.form)
private
method ScanBtn_Click(sender: System.Object; e: System.EventArgs);
protected
public
Method UpdateButtons;
end;
Method Mainform.UpdateButtons;
begin
Button1.enabled:=true;
Button1.text:='Start Scanning';
end;
method MainForm.ScanBtn_Click(sender: System.Object; e: System.EventArgs);
begin
if not Scanning then
stopthread:=true;
dxCommWin.Scan(not Scanning);
UnitWin.UpdateMenu;
UpdateButtons; <-------I call it here instead of from dxCommWin.Scan Method.
end;