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