Jump to content
Magno

How make event be called with an inherited class?

Recommended Posts

I have such class:

type
   TmyNetHTTPClient = class(TNetHTTPClient)
   private
      FileName: String;
      Index: Integer;
      Downloaded: Boolean;
      FileStream: TFileStream;
   public
      procedure ReceiveData(const Sender: TObject; AContentLength, AReadCount: Int64; var Abort: Boolean);
      procedure RequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse);
   end;

Now I create my object and have some similar:
 

// consider filestream already created and other needs for the sake of this example
begin
  myNetHTTPClient := TmyNetHTTPClient.Create(self);
  myNetHTTPClient.Get('http://localhost/file.txt', FileStream);
  //myNetHTTPClient.onReceiveData; // error, so commented
end;

 

Now, what is I am doing wrong here? The ReceiveData(), and also RequestCompleted() are never triggered 😕

 

procedure TDownloader.ReceiveData(const Sender: TObject; AContentLength, AReadCount: Int64; var Abort: Boolean);
begin
   doSomething();
end;

What should I do to make it work?

 

 

 

 

Share this post


Link to post

In your class constructor, you should assign these events, something like:


 

constructor TmyNetHTTPClient.Create()

begin

  inherited Create;

  OnReceiveData := ReceiveData;

  OnRequestComplewted := RequestCompleted;

end;

 

  • Thanks 1

Share this post


Link to post
13 minutes ago, Jacek Laskowski said:

In your class constructor, you should assign these events, something like:


 


constructor TmyNetHTTPClient.Create()

begin

  inherited Create;

  OnReceiveData := ReceiveData;

  OnRequestComplewted := RequestCompleted;

end;

 

YES!!!!!

I missed this understanding!! Thank you so much!! 😄

 

Share this post


Link to post
8 hours ago, Magno said:

OnReceiveData := ReceiveData;

I'm a bit puzzled here, because usually it is a big no-no to assign code to a published event in a descendant component. Because the event is still published and anybody using your component can assign something else to this event and your added functionality is gone.

Usually you should override the method which calls the event, add the functionality and call inherited.

Only: Looking at the source code I see that this method (DoReceiveData) is both private and not virtual, so there's no chance to do it this way.

 

I wonder whether there's a reason the Delphi developers did it that way, or why have they abandoned the usual component design patterns?

 

Anyway, I would at least unpublish these events, along the lines in

https://stackoverflow.com/questions/53677049/hide-properties-and-events-in-new-component

  • Like 4

Share this post


Link to post
Guest
1 hour ago, Renate Schaaf said:

I wonder whether there's a reason the Delphi developers did it that way, or why have they abandoned the usual component design patterns?

Simply put, sloppy work done by developers who don't understand the Delphi soul.

Share this post


Link to post
38 minutes ago, Kas Ob. said:

Simply put, sloppy work done by developers who don't understand the Delphi soul.

I didn't dare to say that, but that's what I thought:)

 

Now I wonder whether there is a way to make this safe short of changing the source code or writing a wrapper component with a TNetHTTPClient as a subcomponent and exposing its things as needed, which seems to be a lot of work.
 

Share this post


Link to post
Guest
2 hours ago, Renate Schaaf said:

I didn't dare to say that, but that's what I thought:)

Don't do that, you paid them money they asked for, they dared to fail for years to provide the quality after receiving money, at least you should ask for quality worth for your money and time, it might help prevent such sloppy work for the future.

 

I never used this TNetHTTPClient , but i can list few approach's to consider

1) Override with copy and paste, this is ugly and might not work if those methods are using private fields/methods, even it did work might not be compatible with future versions.

2) Have a look at https://github.com/MahdiSafsafi/DDetours it can do magic, but does need special experience level, so the level you must have to use this library range from novice to guru, based on your mission, check it anyway you might need it in the furute.

3) Ditch TNetHTTPClient and look for alternative (there is dozens), most likely will find higher quality and better functionality.

Share this post


Link to post
15 minutes ago, Kas Ob. said:

3) Ditch TNetHTTPClient and look for alternative (there is dozens), most likely will find higher quality and better functionality. 

NetHTTPClient has one huge advantage... When working with SSL/TLS it uses the system api and you don't have to fight with openssl, certificates etc.

  • Like 2

Share this post


Link to post
4 hours ago, Renate Schaaf said:

I wonder whether there's a reason the Delphi developers did it that way, or why have they abandoned the usual component design patterns?

There are TONS of places throughout the VCL where the original developers could be accused of not thinking through the various use-cases enough to have a clear idea of what methods should have been tagged as protected rather than private. I think they tended to err on the side of keeping things private that didn't have obvious reasons to override them at the time. 

 

I see plenty of libs where the devs went the other way and stuffed nearly everything into the protected section instead of private, leaving a huge invitation to hack the crap out of things.

 

I've often run into this situation in my own code, where I needed to override a method in a child class but I left it as private in the parent/base class instead of protected. It just didn't occur to me that I'd ever want to use it in a child class.

 

Honestly, this is an area that you could spend a ton of time sweating over prior to a product release, and if you're in a hurry like most projects, it just never gets addressed.

 

And that's why there are hacks for that ...

  • Like 2

Share this post


Link to post
Guest
Just now, Jacek Laskowski said:

NetHTTPClient has one huge advantage... When working with SSL/TLS it uses the system api and you don't have to fight with openssl, certificates etc.

If the point is to have the TLS connection then it is valid point, but many other (may be all) libraries have it too!, it is almost everywhere, even Delphi Html Component implement those ~30 functions, EurekaLog does have it....

 

And i am not talking about is it security level, i have no idea, i know for sure the IDE itself for years didn't have secure connection and when it did have it, it is useless as trash, as it will accept in expired certificate, even when the name is not matching the connection will be successful established and data will be sent, useless shell with traffic overhead.

When it comes for security, don't trust a chef that use a microwave to prepare you "fancy pricey food".

Share this post


Link to post
33 minutes ago, David Schwartz said:

There are TONS of places throughout the VCL where the original developers could be accused of not thinking through the various use-cases enough

That's my limited impression after a break of 12 years from Delphi. I paid for all versions up to 2006, now I'm using the community edition, and I am grateful for having the chance this way to come up to par with the new stuff, so I'm a bit reluctant to bash them. I answered here because of general interest in component design, not because I'm particularly interested in this component.

 

1 hour ago, Kas Ob. said:

2) Have a look at https://github.com/MahdiSafsafi/DDetours it can do magic, but does need special experience level, so the level you must have to use this library range from novice to guru, based on your mission, check it anyway you might need it in the furute.

This looks good, I have it tagged.

Share this post


Link to post
4 hours ago, Jacek Laskowski said:

NetHTTPClient has one huge advantage... When working with SSL/TLS it uses the system api and you don't have to fight with openssl, certificates etc.

If you only deal with Windows, check out my https://github.com/Fr0sT-Brutal/Delphi_SChannelTLS set of classes that allow to add OS-provided TLS to any communication transport (even SendMessage 🙂 ) .

But OTOH I wish Emba adopted curl in the form of obj-s.

Share this post


Link to post
On 10/2/2020 at 7:58 AM, Kas Ob. said:

Simply put, sloppy work done by developers who don't understand the Delphi soul.

I did this once, when I made a heavily customized DBGrid component. The custom grid had a default popup menu with basic things (copy, copy all, copy with header, etc). So if there was a popup menu assigned design time, I appended my items. If none, I created one.

Alas, you don't want these options to be available when the grid is empty. So I made a custom onPopup handler to disable these items based on the selected record / field.

But before assigning the new handler, I saved the old handler in a variable and executed it after I enabled / disabled my menu items.

 

I mean, there are things what you only can solve like this, but there is a bad way of doing everything.

However, I too prefer overriding the "DoCall" methods, wherever I can.

Share this post


Link to post

Honestly I don't think the "private" stuff is important for protecting. It's more like for logical structure, exposed API's and the number of shown items in field list. Private items could be changed freely without care about breaking changes but if someone wants to access them, why not let him do it?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×