Call method if declared only
Simen Kjærås
simen.kjaras at gmail.com
Fri Feb 28 08:23:22 UTC 2020
On Friday, 28 February 2020 at 08:08:59 UTC, Виталий Фадеев wrote:
> On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев
> wrote:
>> Searching solution for idea !
>>
>> Goal is to get System message, dispatch/route to method !
>> If method implemented only !
>>
>> I dream on in future write clean code of a derived widgets
>> like this :
>>
>> class Base
>> {
>> // dispatch
>> void On( message ... )
>> {
>> // call On<message>()
>> // example: call OnKeyUp() - if method OnKeyUp() is
>> exists only
>> }
>> }
>>
>> May be other than derived ? May be templating ?
>> How to implement ?
>
> Now I go in ths way:
[snip]
> Searching for beauty readable code...
Here's an attempt. It looks up all subclasses of Base in the same
module, and calls the named method if it exists. However, it will
fail for any subclass of Base that is defined in a different
module.
import core.sys.windows.windows;
import std.stdio;
class Base {
LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_KEYDOWN:
return tryCall!"OnWM_KEYDOWN"(wParam, lParam);
default:
}
return 0;
}
auto tryCall(string name, Args...)(Args args) {
import std.meta;
alias This = typeof(this);
alias module_ = __traits(parent, This);
enum isSubclass(T...) = is(T[0] : This);
alias getModuleMember(string name) = __traits(getMember,
module_, name);
enum hasMethod(T) = __traits(hasMember, T, name);
// Get every member in this module
enum memberNames = __traits(allMembers, module_);
alias members = staticMap!(getModuleMember, memberNames);
// Filter away anything that isn't derived from Base
alias subclasses = Filter!(isSubclass, members);
// Get rid of anything that doesn't have a method with
the correct name
alias subclassesWithMethod = Filter!(hasMethod,
subclasses);
// Sort them so you get the most derived types first
alias Types = DerivedToFront!subclassesWithMethod;
// Check for each type if the `this` is an instance of
that specific one
static foreach (T; Types) {
if (cast(T)this !is null) {
// And look up that method and call it.
return __traits(getMember, cast(T)this,
name)(args);
}
}
// If `this` is not one of the types with that method,
return some default value
return 0;
}
}
class Button : Base {
LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) {
writeln("WM_KEYDOWN");
return 0;
}
}
unittest {
Base b1 = new Base();
Base b2 = new Button();
writeln("Base:");
b1.On(WM_KEYDOWN, 0, 0);
writeln("Button:");
b2.On(WM_KEYDOWN, 0, 0);
}
--
Simen
More information about the Digitalmars-d-learn
mailing list