Featured post

c# - Usage of Server Side Controls in MVC Frame work -

i using asp.net 4.0 , mvc 2.0 web application. project requiremrnt have use server side control in application not possibl in noraml case. ideally want use adrotator control , datalist control. i saw few samples , references in codepleax mvc controllib howwver found less useful. can tell how utilize theese controls in asp.net application along mvc. note: please provide functionalities related adrotator , datalist controls not equivalent functionalities thanks in advace. mvc pages not use normal .net solution makes use of normal .net components impossible. a normal .net page use event driven solution call different methods service side mvc use actions , view completly different way handle things. also, mvc not use viewstate normal .net controlls require. found article discussing mixing of normal .net , mvc.

delphi - How to test the type of a generic interface? -


i'm not sure if title makes sense, hope can understand question code.

given following code publish/subscribe framework.

type   imessage = interface     ['{b1794f44-f6ee-4e7b-849a-995f05897e1c}']   end;    isubscriber = interface     ['{d655967e-90c6-4613-92c5-1e5b53619ee0}']   end;    isubscriberof<t: imessage> = interface(isubscriber)     procedure consume(const message: t);   end;    tmessageservice = class   private     fsubscribers: tlist<isubscriber>;   public     constructor create;     destructor destroy; override;     procedure sendmessage(const message: imessage);     procedure subscribe(const subscriber: isubscriber);     procedure unsubscribe(const subscriber: isubscriber);   end; 

that used this:

tmymessage = class(tinterfacedobject, imessage);  tmysubscriber = class(tinterfacedobject, isubscriberof<tmymessage>)   procedure consume(const message: tmymessage); end;  tmyothermessage = class(tinterfacedobject, imessage);  tmyothersubscriber = class(tinterfacedobject, isubscriberof<tmyothermessage>)   procedure consume(const message: tothermessage); end; 

how can loop subscribers list , send message proper subscribers?

the subscribers list have subscribers types of messages. sendmessage have find subscribers type of message provided param , send whom implements proper interface consume type of message.

  procedure tmessageservice.sendmessage(const message: imessage);   var     subscriber: isubscriber;   begin     subscriber in fsubscribers     begin       // how send message subscribers of correspondent type of message     end;   end; 

thanks!

btw, code based on blog post.

edit: found way make less convoluted (please vote on answer this; took quite while right).
note uses new rtti unit, works only delphi 2010 , (i used delphi xe developing this, did not yet verify in delphi 2010).

for supports, need store iid guids with interfaces , means query them.
since want use generics, want able query iid guid interface type, not interface reference (as hallvard vassbotn showed hack in 2006).
new rtti introduced in delphi 2010 allows that:

unit rttiunit;  interface  type   trtti = record     //1 similar http://hallvards.blogspot.com/2006/09/hack11-get-guid-of-interface-reference.html interface type, not reference     class function getinterfaceiid<t: iinterface>(var iid: tguid): boolean; static;   end;  implementation  uses   typinfo,   rtti;  class function trtti.getinterfaceiid<t>(var iid: tguid): boolean; var   typeinfooft: ptypeinfo;   rtticontext: trtticontext;   rttiinterfacetype: trttiinterfacetype;   rttitype: trttitype; begin   typeinfooft := typeinfo(t);   rtticontext := trtticontext.create();    rttitype := rtticontext.gettype(typeinfooft);   if rttitype trttiinterfacetype   begin     rttiinterfacetype := rttitype trttiinterfacetype;     iid := rttiinterfacetype.guid;     result := true;   end   else     result := false; end;  end. 

so changed code, rearranged bit, , spread on more units keep overview.

classicmessagesubscriberunit: has non generic interfaces imessage , isubscriber (they descend iimplementedwithclass makes easier log things.

unit classicmessagesubscriberunit;  interface  type   iimplementedwithclass = interface(iinterface)     function tostring: string;   end;    imessage = interface(iimplementedwithclass)     ['{b1794f44-f6ee-4e7b-849a-995f05897e1c}']   end;    isubscriber = interface(iimplementedwithclass)     ['{d655967e-90c6-4613-92c5-1e5b53619ee0}']   end;  implementation  end. 

genericsubscriberofunit: contains generic isubscriberof interface descends generic isupporterof , generic base implementation called tsupporterof:

unit genericsubscriberofunit;  interface  uses   classicmessagesubscriberunit;  type   isupporterof<t: imessage> = interface(isubscriber)     ['{0905b3eb-b17e-4ad2-98e2-16f05d19484c}']     function supports(const message: t): boolean;   end;    isubscriberof<t: imessage> = interface(isupporterof<t>)     ['{6fd82b1d-61c6-4572-ba7d-d70da9a73285}']     procedure consume(const message: t);   end;  type   tsupporterof<t: imessage> = class(tinterfacedobject, isubscriber, isupporterof<t>)     function supports(const message: t): boolean;   end;  implementation  uses   sysutils,   rttiunit;  function tsupporterof<t>.supports(const message: t): boolean; var   iid: tguid; begin   if trtti.getinterfaceiid<t>(iid)     result := sysutils.supports(message, iid)   else     result := false; end;  end. 

messageserviceunit: contains tmessageservice, type aliases , actual code managing list test it.

unit messageserviceunit;  interface  uses   generics.collections,   classicmessagesubscriberunit,   genericsubscriberofunit;  type   isubscriberofimessage = isubscriberof<imessage>;   tlistisubscriber = tlist<isubscriber>;    tmessageservice = class   private     fsubscribers: tlistisubscriber;   strict protected     procedure consume(const subscriberof: isubscriberofimessage; const message: imessage); virtual;   public     constructor create;     destructor destroy; override;     procedure sendmessage(const message: imessage);     procedure subscribe(const subscriber: isubscriber);     procedure unsubscribe(const subscriber: isubscriber);   end;  implementation  uses   sysutils;  constructor tmessageservice.create; begin   inherited create();   fsubscribers := tlistisubscriber.create(); end;  destructor tmessageservice.destroy; begin   freeandnil(fsubscribers);   inherited destroy(); end;  procedure tmessageservice.sendmessage(const message: imessage); var   localmessage: imessage;   lsubscriber: isubscriber;   lsubscriberof: isubscriberof<imessage>; begin   lsubscriber in fsubscribers   begin     localmessage := message; // prevent premature freeing of message     if supports(lsubscriber, isubscriberof<imessage>, lsubscriberof)       if lsubscriberof.supports(localmessage)         consume(lsubscriberof, localmessage);   end; end;  procedure tmessageservice.subscribe(const subscriber: isubscriber); begin   fsubscribers.add(subscriber); end;  procedure tmessageservice.unsubscribe(const subscriber: isubscriber); begin   fsubscribers.remove(subscriber); end;  procedure tmessageservice.consume(const subscriberof: isubscriberofimessage; const message: imessage); begin   subscriberof.consume(message); end;  end. 

finally unit used test (it uses bo-library @ http://bo.codeplex.com):

unit genericpublishsubscribemainformunit;  interface  uses   windows, messages, sysutils, variants, classes, graphics, controls, forms,   dialogs, stdctrls, loggerinterfaceunit, messageserviceunit,   messagesubscribersunit, classicmessagesubscriberunit;  type   tgenericpublishsubscribemainform = class(tform)     testpublisherbutton: tbutton;     logmemo: tmemo;     procedure testpublisherbuttonclick(sender: tobject);   strict private     flogger: ilogger;   strict protected     function getlogger: ilogger;     property logger: ilogger read getlogger;   public     destructor destroy; override;   end;  type   tloggingmessageservice = class(tmessageservice)   strict private     flogger: ilogger;   strict protected     procedure consume(const subscriberof: isubscriberofimessage; const message: imessage); override;   public     constructor create(const logger: ilogger);     property logger: ilogger read flogger;   end;  var   genericpublishsubscribemainform: tgenericpublishsubscribemainform;  implementation  uses   loggerunit,   outputdebugviewloggerunit,   loggersunit,   messagesunit;  {$r *.dfm}  destructor tgenericpublishsubscribemainform.destroy; begin   inherited destroy;   flogger := nil; end;  function tgenericpublishsubscribemainform.getlogger: ilogger; begin   if not assigned(flogger)     flogger :=  tteelogger.create([       toutputdebugviewlogger.create(),       tstringslogger.create(logmemo.lines)     ]);   result := flogger; end;  procedure tgenericpublishsubscribemainform.testpublisherbuttonclick(sender: tobject); var   loggingmessageservice: tloggingmessageservice; begin   loggingmessageservice := tloggingmessageservice.create(logger);   try     loggingmessageservice.subscribe(tmysubscriber.create() isubscriber);     loggingmessageservice.subscribe(tmyothersubscriber.create() isubscriber);     loggingmessageservice.sendmessage(tmymessage.create());     loggingmessageservice.sendmessage(tmyothermessage.create());       loggingmessageservice.free;   end; end;  constructor tloggingmessageservice.create(const logger: ilogger); begin   inherited create();   flogger := logger; end;  procedure tloggingmessageservice.consume(const subscriberof: isubscriberofimessage; const message: imessage); var   messageimplementedwithclass: iimplementedwithclass;   messagestring: string;   subscribeimplementedwithclass: iimplementedwithclass;   subscriberofstring: string; begin   subscribeimplementedwithclass := subscriberof;   messageimplementedwithclass := message;   subscriberofstring := subscribeimplementedwithclass.tostring;   messagestring := messageimplementedwithclass.tostring; // wrong vmt here, delphi xe sp2   logger.log('consume(subscriberof: %s, message:%s);',     [subscriberofstring, messagestring]); //    [subscriberof.classtype.classname, message.classtype.classname]);   inherited consume(subscriberof, message); end;  end. 

--jeroen

old solution:

this might it, still find solution bit convoluted.

messageserviceunit: isubscriberof has guid , supports method check if imessage in fact supported.

unit messageserviceunit;  interface  uses   generics.collections;  type   imessage = interface(iinterface)     ['{b1794f44-f6ee-4e7b-849a-995f05897e1c}']   end;    isubscriber = interface(iinterface)     ['{d655967e-90c6-4613-92c5-1e5b53619ee0}']   end;    isubscriberof<t: imessage> = interface(isubscriber)     ['{6fd82b1d-61c6-4572-ba7d-d70da9a73285}']     procedure consume(const message: t);     function supports(const message: t): boolean;   end;    tmessageservice = class   private     fsubscribers: tlist<isubscriber>;   public     constructor create;     destructor destroy; override;     procedure sendmessage(const message: imessage);     procedure subscribe(const subscriber: isubscriber);     procedure unsubscribe(const subscriber: isubscriber);   end;  implementation  uses   sysutils;  constructor tmessageservice.create; begin   inherited create(); end;  destructor tmessageservice.destroy; begin   inherited destroy(); end;  procedure tmessageservice.sendmessage(const message: imessage); var   lsubscriber: isubscriber;   lsubscriberof: isubscriberof<imessage>; begin   lsubscriber in fsubscribers   begin     if supports(lsubscriber, isubscriberof<imessage>, lsubscriberof)       if lsubscriberof.supports(message)         lsubscriberof.consume(message);   end; end;  procedure tmessageservice.subscribe(const subscriber: isubscriber); begin   fsubscribers.add(subscriber); end;  procedure tmessageservice.unsubscribe(const subscriber: isubscriber); begin   fsubscribers.remove(subscriber); end;  end. 

messagesunit: messages each have interface guid supports can check guid.

unit messagesunit;  interface  uses   messageserviceunit;  type   imymessage = interface(imessage)     ['{84b42ec8-cac0-44b4-97a8-05ae5b636236}']   end;   tmymessage = class(tinterfacedobject, imessage, imymessage);    imyothermessage = interface(imessage)     ['{ab323765-ff7b-4852-91aa-b7ecc1845b41}']   end;   tmyothermessage = class(tinterfacedobject, imessage, imyothermessage);  implementation  end. 

messagesubscribersunit: subscribers have supports method checking right guid.

unit messagesubscribersunit;  interface  uses   messagesunit, messageserviceunit;  type   tmysubscriber = class(tinterfacedobject, isubscriberof<imymessage>)     procedure consume(const message: imymessage);     function supports(const message: imymessage): boolean;   end;    tmyothersubscriber = class(tinterfacedobject, isubscriberof<imyothermessage>)     procedure consume(const message: imyothermessage);     function supports(const message: imyothermessage): boolean;   end;  implementation  uses   sysutils;  procedure tmysubscriber.consume(const message: imymessage); begin   // end;  function tmysubscriber.supports(const message: imymessage): boolean; begin   result := sysutils.supports(message,  imymessage); end;  procedure tmyothersubscriber.consume(const message: imyothermessage); begin   // end;  function tmyothersubscriber.supports(const message: imyothermessage): boolean; begin   result := sysutils.supports(message,  imyothermessage); end;  end. 

messagesunit: contains specific messages (both interface , class types), contain iid guids distinguish them supports.

unit messagesunit;  interface  uses   messageserviceunit,   classicmessagesubscriberunit;  type   imymessage = interface(imessage)     ['{84b42ec8-cac0-44b4-97a8-05ae5b636236}']   end;   tmymessage = class(tinterfacedobject, imessage, imymessage);    imyothermessage = interface(imessage)     ['{ab323765-ff7b-4852-91aa-b7ecc1845b41}']   end;   tmyothermessage = class(tinterfacedobject, imessage, imyothermessage);  implementation  end. 

messagesubscribersunit: contains specific subscribers (both interface , class types), not need supports method more: contain consume method.

unit messagesubscribersunit;  interface  uses   messagesunit,   messageserviceunit,   genericsubscriberofunit,   classicmessagesubscriberunit;  type   tmysubscriber = class(tsupporterof<imymessage>, isubscriber, isubscriberof<imymessage>)     procedure consume(const message: imymessage);   end;    tmyothersubscriber = class(tsupporterof<imyothermessage>, isubscriber, isubscriberof<imyothermessage>)     procedure consume(const message: imyothermessage);   end;  implementation  uses   sysutils;  procedure tmysubscriber.consume(const message: imymessage); begin   // end;  procedure tmyothersubscriber.consume(const message: imyothermessage); begin   // end;  end. 

--jeroen


Comments

Popular posts from this blog

c# - Usage of Server Side Controls in MVC Frame work -

cocoa - Nesting arrays into NSDictionary object (Objective-C) -

ios - Very simple iPhone App crashes on UILabel settext -