On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев wrote:
Searching solution for idea !

For whatever reason, it seems my attempts at answering this earlier has disappeared into the void. Here:

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);
}

Now, this only works for subclasses defined in the same module. A possibly better solution would be interfaces:

import core.sys.windows.windows;
import std.stdio;

class Base {
    LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message) {
            case WM_KEYDOWN:
                if (cast(IKeyDown)this) {
return (cast(IKeyDown)this).OnWM_KEYDOWN(wParam, lParam);
                }
            default:
        }
        return 0;
    }
}

interface IKeyDown {
    LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam);
}

class Button : Base, IKeyDown {
    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
  • Call method if declare... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Simen Kjærås via Digitalmars-d-learn
      • Re: Call meth... Виталий Фадеев via Digitalmars-d-learn
        • Re: Call ... drug via Digitalmars-d-learn
        • Re: Call ... Simen Kjærås via Digitalmars-d-learn
          • Re: C... Виталий Фадеев via Digitalmars-d-learn
            • ... Виталий Фадеев via Digitalmars-d-learn
              • ... Виталий Фадеев via Digitalmars-d-learn
                • ... Simen Kjærås via Digitalmars-d-learn
                • ... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Alexandru Ermicioi via Digitalmars-d-learn

Reply via email to