class function RTL.Supports (const aClass: TClass; const IID: TGUID): Boolean;
begin
Result := aClass.GetInterfaceEntry (IID) <> nil;
end;
Is it possible to do the same with Oxygene?
I did look at ShineOn but there is no overload for testing if a class supports a specific interface.
EDIT
I am porting code from Delphi to Oxygene, thus the interfaces do not have Guids so I’m looking for an implementation of an equivalent method something along the lines of:
class method RTL.Supports (const aClass: System.Type; const IID: System.Type): Boolean;
begin
Result := ....
end;
That is correct, I do not have an instance at hand so the is operator is no good to me.
What I have is a reference to a System.Type which is the type MyClass where MyClass = class of MyObject
I tried this but it does not work. The interfaces that I have implemented on a class are not in the GetInterfaces array.
class method RTL.Supports <TClass, TInterface>: Boolean;
begin
var classType: System.Type := typeOf(TClass);
var intfType: System.Type := typeOf(TInterface);
if classType.IsClass and intfType.IsInterface then begin
var interfaces: array of System.Type := classType.GetType.GetInterfaces;
for each intf: System.Type in interfaces do begin
if intf.Equals (intfType) then begin
exit True;
end;
end;
end;
end;
class method RTL.Supports <TClass, TInterface>: Boolean;
begin
var classType: System.Type := typeOf(TClass);
var intfType: System.Type := typeOf(TInterface);
if classType.IsClass and intfType.IsInterface then begin
exit intfType.IsAssignableFrom(classType);
end;
end;
...
if RTL.Supports<TFoo, IFoo> then begin
// never reached even though TFoo implements IFoo
end;
namespace ConsoleApplication113;
interface
uses
System.Linq;
type
ImyItnf = public interface end;
ConsoleApp = class(ImyItnf)
public
class method Main(args: array of String);
class method Supports <TClass, TInterface>: Boolean;
end;
implementation
class method ConsoleApp.Supports <TClass, TInterface>: Boolean;
begin
var classType: System.Type := typeOf(TClass);
var intfType: System.Type := typeOf(TInterface);
if classType.IsClass and intfType.IsInterface then begin
exit intfType.IsAssignableFrom(classType);
end;
end;
class method ConsoleApp.Main(args: array of String);
begin
Console.WriteLine('Hello World: '+Supports<ConsoleApp, ImyItnf>);
end;
end.
Ok figured it out.
If the class is declared in the implementation scope it is not assignable.
I assume because the class is private.by default if defined in the implementation scope.
So in the context of preparing my Delphi library for compilation in Oxygene I would have to move 370 class definitions into the interface area. I was hoping to maintain a single code base with an automated parser that ‘cleans’ the Delphi code and exports Oxygene compatible code. Such a big change would certainly result in maintaining two code bases.
In the Delphi library the class definitions are deliberately hidden so un-hiding them is something I want to avoid.
Hrmm I can’t reprodce that locally, this works fine:
namespace ConsoleApplication113;
interface
uses
System.Linq;
type
ConsoleApp = class
public
class method Main(args: array of String);
class method Supports <TClass, TInterface>: Boolean;
end;
type
IFoo = interface;
implementation
type
TFoo = class(Object, IFoo);
class method ConsoleApp.Supports <TClass, TInterface>: Boolean;
begin
var classType: System.Type := typeOf(TClass);
var intfType: System.Type := typeOf(TInterface);
if classType.IsClass and intfType.IsInterface then begin
exit intfType.IsAssignableFrom(classType);
end;
end;
class method ConsoleApp.Main(args: array of String);
begin
Console.WriteLine('Hello World: '+Supports<TFoo, IFoo>);
end;
end.
Your console app works fine but the function fails in my windows app.
I will do some foraging and let you know if I find something of interest.
For those who found this interesting here is the code that does work correctly for me, and also closer to what I was trying to achieve to start with. The RTL.Supports function will be used to test whether a given class supports a specific interface prior to being registered with a class factory. In turn the class factory will make new instances of objects that support the requested interface using the handy RTLClass.create method. The end goal is to have Delphi and Oxygene compatibile way of creating instances as follows: Factory.Make<IFoo>: RTLInterface;
interface
type
RTLInterface = interface;
RTLClass = class of RTLObject;
RTLObject = public class (Object, RTLInterface);
RTL = public class
public
class method Supports<T>(aClass: RTLClass): Boolean; where T is RTLInterface;
end;
IFoo = interface (RTLInterface);
implementation
type
TFoo = class (RTLObject, IFoo)
end;
class method RTL.Supports <T>(aClass: RTLClass): Boolean;
begin
var classType: System.Type := aClass.ActualType;
var intfType: System.Type := typeOf(T);
if assigned(classType) and classType.IsClass and intfType.IsInterface then begin
exit intfType.IsAssignableFrom(classType);
end;
end;
end.