Bill Meyer 337 Posted December 14, 2019 (edited) Is there any way to refer to the unit name in the unit's code? The question arises in connection with logging, and the convenience it would bring not to have to manually enter the unit name in those calls. Something like: LogThis(ThisUnit, SomeValue); If this were only an occasional need, it would not matter, but I have hundreds units into which to add the calls. Edited December 14, 2019 by Bill Meyer Share this post Link to post
Uwe Raabe 2064 Posted December 14, 2019 (edited) If this call happens inside a method or class method in that unit, you can use UnitName for that. Every class returns the unit of its declaration with this function. See: http://docwiki.embarcadero.com/Libraries/Rio/en/System.TObject.UnitName As it is a class method, you can even make use of it outside of that class as long as there is at least one class declared in that unit. Edited December 14, 2019 by Uwe Raabe Share this post Link to post
Bill Meyer 337 Posted December 14, 2019 1 hour ago, Uwe Raabe said: If this call happens inside a method or class method in that unit, you can use UnitName for that. Every class returns the unit of its declaration with this function. See: http://docwiki.embarcadero.com/Libraries/Rio/en/System.TObject.UnitName I thought I remembered UnitName in some hazy way. But the issue here is that I need to add logging into an initialization section, and not all of those are calling into classes. I am simply trying to find the least change needed to get the log to demonstrate the initialization order. Then I will apply that sequence in a module in which I manage the initialization sequence, and in each module, the initialization and finalization will be replaced by procedures InitializeUnit and FinalizeUnit, which contain the original code. The issue is that the initialization sequence contains some traps, in that there are sequence dependencies, and on the way to a complete solution, making the order explicit in my code shields me from the shifting sands when changes are made to uses clauses. This in turn is a concern because of massive unit dependencies I am trying to reduce. As I learned painfully some months ago, removing unneeded unit references can cause the execution order of those initializations to change. And yes, in the long run, refactoring and redesign is needed, but meanwhile, I have a couple thousand units in a large legacy app which must first be made stable. Share this post Link to post
Uwe Raabe 2064 Posted December 15, 2019 As I said, you can call UnitName on every class declared in that unit. If the unit contains no suitable class declaration in the first place, you can always add one just for this purpose: type TClassInThisUnit = class; initialization LogThis(TClassInThisUnit.UnitName, SomeValue); end. 1 1 Share this post Link to post
Uwe Raabe 2064 Posted December 15, 2019 (edited) You can also create an include file with the following content type TLog = class public class procedure This(const Msg:string); end; class procedure TLog.This(const Msg: string); begin LogThis(UnitName, Msg); end; In your units add an appropriates include directive directly below the implementation uses. Then replace all LogThis calls with TLog.This calls, without bothering about the unit name at all. Edited December 15, 2019 by Uwe Raabe Share this post Link to post
David Heffernan 2353 Posted December 15, 2019 (edited) Parsing the detailed map file is probably the easiest way to do this is a large project. If you know you have dependencies on initialization order, I'd solve the problem by removing those dependencies. Edited December 15, 2019 by David Heffernan 1 Share this post Link to post
dummzeuch 1517 Posted December 15, 2019 1 hour ago, Uwe Raabe said: You can also create an include file with the following content type TLog = class public class procedure This(const Msg:string); end; class procedure TLog.Line(const Msg: string); begin LogThis(UnitName, Msg); end; In your units add an appropriates include directive directly below the implementation uses. Then replace all LogThis calls with TLog.This calls, without bothering about the unit name at all. Shouldn't that be: class procedure TLog.This(const Msg: string); begin LogThis(UnitName, Msg); end; 1 Share this post Link to post
A.M. Hoornweg 144 Posted December 15, 2019 8 hours ago, David Heffernan said: Parsing the detailed map file is probably the easiest way to do this is a large project. If you know you have dependencies on initialization order, I'd solve the problem by removing those dependencies. Is the sequence of the units in the map file identical to the sequence in which the initialization sections are processed? Share this post Link to post
David Heffernan 2353 Posted December 15, 2019 Actually, I think that might be right, there is a section in the map file that lists the units in the order they are initialized. Also, there are tons of questions on this topic on SO. Share this post Link to post
Uwe Raabe 2064 Posted December 15, 2019 30 minutes ago, David Heffernan said: there is a section in the map file that lists the units in the order they are initialized. That is the ICODE section (probably stands for initialization code). Share this post Link to post