How to catch events of a class in a class helper? - class

I want to create a helper for TCustomQuery, TQuery, TTable and so on... With a LastRecordPosition property, which I will get with OnBeforeScroll setting that property from RecNo.
How do I create that trigger in that helper class to catch the event without interfere in an user's OnBeforePost if he/she needs one?
I use FireDAC or ZeosLib for older versions.

To intercept the OnBeforeScroll event without interfering with the user's OnBeforeScroll event handler, you need to override each component's virtual DoBeforeScroll() method. However, a class helper cannot override any virtual methods of the class it is helping. So, you will have to instead either:
write new classes that are derived from each base component class you want to intercept (type TMyCustomQuery = class(TCustomQuery), etc), and then the user must use those new component classes in their code instead of the originals.
(XE and later only) use Delphi's TVirtualMethodInterceptor class to hook the virtual DoBeforeScroll() method of specific component object instances (not the classes themselves) without having to write any derived classes.
The alternative is to write a class, possibly a Generic class, that the user has to instantiate for each component object instance, and the class can then subclass its associated component (possibly with RTTI) to capture and replace the user's OnBeforeScroll event handler with its own, and then its event handler can call the user's event handler when needed.

Related

Subscribing to Object value or associated change

Is there some doco on IAutoSubscriptionService.
How do I use using (ESP.GetEcoService().StartSubscribe(subscriber)) to trigger an event when an object changes. That is for any attribute of an object.
The StartSubscribe gives a IDisposable context back and it is typically used like this:
using (theAutoSubscriptionService.StartSubscribe(subscriber))
{
arbitrary c# code accessing model elements
- all access will be added to subscription!
A thing of beauty really!
}
When something later change - the ISubscriber.Receive will fire.
For adhoc usage consider the EventSubscriber class

Using Zenject to inject an implementation with interfaces

I'm trying to use Zenject in Unity. I have an interface and several implementations of it.
I want to inject with ID but also that the implementation will have the tick interface since it's not a MonoBehaviour.
So I have an IAttacker interface and a MeleeAttackImpl implementation.
Container.Bind<IAttacker>().WithId(AttackerTypeEnum.MELEEE).To<MeleeAttackImpl>().AsTransient();
I want to add
Container.BindInterfacesTo<MeleeAttackImpl>().AsTransient();
But it creates 2 different objects instead of instances that have the Tick interface and bind them to IAttacker.
If you want to bind an interface to a determined implementation, why do you use two bindings?
If you want only one instance of the object I would try:
Container.BindInterfacesAndSelfTo<MeleeAttackImpl>().AsSingle();
or:
Container.Bind<IAttacker>().To<MeleeAttackImpl>().AsSingle();
As Single() In the case you need the same instance provided from the container along the app (like a singleton).
From the documentation:
"AsTransient - Will not re-use the instance at all. Every time ContractType is requested, the DiContainer will execute the given construction method again."
Many times intance is created in the binding itself. So maybe from the two binding two instances are created, one from each binding.
In case you need to create instances dynamically with all their dependencies resolved, what you need a is Factory.

AnyLogic - create objects dynamically on simulation time

Is it possible to dynamically create objects or modify them on run-time ?for example,on button click,another button created or change number of lines of a road?
When I write this code for a button Action,in run-time
road123.setBackwardLanesCount(3);
I get error below:
root:
road123: Markup element is already initiated and cannot be modified.Please use constructor without arguments,perform setup and finally call initialize() .function
You'll get that error with any object you attempt to create at runtime using a parameterized constructor. If you create the object with a simple constructor (just "()") and then set all of the parameters individually, you won't run into that issue. Check the Anylogic API for specific information about the object you are using, because some require you to call .initiliaze() on that object after setting all of it's parameters if you created it using a simple constructor. Furthermore, if you want to add the object to the screen at runtime you'll need to add this code to the function that creates it:
#Override
public void onDraw( Panel panel, Graphics2D graphics) {
obj.drawModel(panel, graphics, true);
}
where obj is replaced with the name of the object you created dynamically.

Loading related objects without Include()

Briefly, I'm loading objects that descend from a base class using a repository defined against the base class. Although my objects are created with the correct descendant classes, any descendant classes that add navigation properties not present in the base class do not have those related objects loaded, and I have no way to explicitly request them.
Here is a simple method in a repository class that loads a given calendar event assuming you know its ID value:
public CalendarEvent GetEvent(int eventId)
{
using (var context = new CalendarEventDbContext(ConnectionString))
{
var result = (from evt in context.CalendarEvents
where eventId.Equals((int)evt.EventId)
select evt).ToList();
return result.ToList()[0];
}
}
CalendarEvent is a base class from which a large number of more specific classes descend. Entity Framework correctly determines the actual class of the calendar event specified by eventId and constructs and returns that derived class. This works perfectly.
Now, however, I have a descendant of CalendarEvent called ReportIssued. This object has a reference to another object called ReportRequest (another descendant of CalendarEvent, although I don't think that's important).
My problem is that when Entity Framework creates an instance of ReportIssued on my behalf I always want it to create and load the related instance of ReportRequested, but because I am creating the event in the context of generic calendar events, although I correctly get back a ReportIssued event, I cannot specify the .Include() to get the related object. I want to do it through this generically-expressed search because I won't necessarily know the type of eventId's event and also I have several other "Get" methods that return collections of CalendarEvent descendants.
I create my mappings using the Fluent API. I guess what I'm looking for is some way to express, in the mapping, that the related object is always wanted or, failing that, some kind of decorator that expresses the same concept.
I find it odd that when saving objects Entity Framework always walks the entire graph whereas it does not do the equivalent when loading objects.

Gin injecting in a shared (client server) object - "IsTreeItem"

I have an object that implements "IsTreeItem". The Object is displayed as a two level tree item. Each tree item is built with a check box.
I need to know when a check box is changing value - so i am listening to ValueChangedEvents.
The first problem is that the Tree built with such items only fires SelectionEvents. If selection is changing the check box the ValueChanged event is fired afterwards - so there is no way to listen to events inside "IsTreeItem" from Tree.
So i let my "IsTreeItem" fire its own element. So i (field)injected an EventBus and used it to fire the event if "ValueChanged".
The Problem is that my "IsTreeItem" is an Object sent from server (it is in shared package and serializable). The object is instantiated on server (EventBus is not ionjected) and "asTreeItem" is called on client.
Is there a way to inject the EventBus in the Method TreeItem asTreeItem() in some way? Or are there any other means to let some one outside know if a check box has changed its value.
GIN can do member injection on already created instances.
You have to create a method in your Ginjector interface that takes such an instance as argument, with a return type of void.
Note that because no reflection is done on the client, GIN will only inject fields and methods from the class used as the argument type (and its super-classes).
#GinModules(MyGinModule.class)
interface MyGinjector extends Ginjector {
…
void injectIsTreeItemMembers(IsTreeItem item);
}