digitalmars.D.learn - Any idea for a solution to handle overloads when dynamically
- Gary Willoughby (20/20) Sep 09 2013 Just wondered if i could pick you brains for a nice solution to
- H. S. Teoh (34/61) Sep 11 2013 One idea I have is to use the built-in "typetuples" as a way of
- Gary Willoughby (3/67) Sep 12 2013 Thanks for the idea, i have implemented something based on this
Just wondered if i could pick you brains for a nice solution to dynamically add methods to a class, paying particular attention to overloads. I'm currently writing a mocking framework and everything's coming along nicely and i'm wondering how to handle replacing overloads of the mocked class. To create a new mocked class this is the code: auto mock = new Mock!Person(); Simple enough, mock now contains an extended class with all the methods set to assert(false) because there are no implementations yet. What i need to do is to add the implementations dynamically. This is the code i propose. mock.addMethod("getAge", int delegate(){ return 40; }); assert(mock.getAge() == 40); Which i guess would be easy to implement but it doesn't handle overloads because the method string doesn't contain enough information to define which overload it's implementing. Any nice ideas what would be a nice way of supporting this? I thought i'd ask while i have a think and get some tea. :)
Sep 09 2013
On Mon, Sep 09, 2013 at 10:16:42PM +0200, Gary Willoughby wrote:Just wondered if i could pick you brains for a nice solution to dynamically add methods to a class, paying particular attention to overloads. I'm currently writing a mocking framework and everything's coming along nicely and i'm wondering how to handle replacing overloads of the mocked class. To create a new mocked class this is the code: auto mock = new Mock!Person(); Simple enough, mock now contains an extended class with all the methods set to assert(false) because there are no implementations yet. What i need to do is to add the implementations dynamically. This is the code i propose. mock.addMethod("getAge", int delegate(){ return 40; }); assert(mock.getAge() == 40); Which i guess would be easy to implement but it doesn't handle overloads because the method string doesn't contain enough information to define which overload it's implementing. Any nice ideas what would be a nice way of supporting this? I thought i'd ask while i have a think and get some tea. :)One idea I have is to use the built-in "typetuples" as a way of disambiguating between different overloads. For example, something like this: // This captures the function argument type list in a form that // we can call .mangleof on. template ArgTypesWrapper(ArgTypes...) { } // This builds a unique string to identify a specific overload // based on the function name and the .mangleof of its argument // types. The key to this trick is that the .mangleof of a // template encodes its argument types, so it is unique per // combination of argument types. template FuncSignature(string funcName, ArgTypes...) { enum FuncSignature = funcName ~ ArgTypesWrapper.mangleof; } class Mock(... /* whatever you currently have here */) { // This unfortunately has to be a template function in // order to be able to capture the argument types of the // delegate in the typetuple A. This may complicate the // implementation of how you'd actually dispatch to the // overload implementation at runtime. void addMethod(R, A...)(string funcName, R delegate(A...) dg) { string overloadName = FuncSignature!(funcName, A); // Now overloadName should be a unique string // representing that particular combination of // function name and argument types, i.e., it's // a function signature. So you can use it to // identify which overload is which. } } T -- Meat: euphemism for dead animal. -- Flora
Sep 11 2013
On Wednesday, 11 September 2013 at 18:24:31 UTC, H. S. Teoh wrote:On Mon, Sep 09, 2013 at 10:16:42PM +0200, Gary Willoughby wrote:Thanks for the idea, i have implemented something based on this and it seems to be working well.Just wondered if i could pick you brains for a nice solution to dynamically add methods to a class, paying particular attention to overloads. I'm currently writing a mocking framework and everything's coming along nicely and i'm wondering how to handle replacing overloads of the mocked class. To create a new mocked class this is the code: auto mock = new Mock!Person(); Simple enough, mock now contains an extended class with all the methods set to assert(false) because there are no implementations yet. What i need to do is to add the implementations dynamically. This is the code i propose. mock.addMethod("getAge", int delegate(){ return 40; }); assert(mock.getAge() == 40); Which i guess would be easy to implement but it doesn't handle overloads because the method string doesn't contain enough information to define which overload it's implementing. Any nice ideas what would be a nice way of supporting this? I thought i'd ask while i have a think and get some tea. :)One idea I have is to use the built-in "typetuples" as a way of disambiguating between different overloads. For example, something like this: // This captures the function argument type list in a form that // we can call .mangleof on. template ArgTypesWrapper(ArgTypes...) { } // This builds a unique string to identify a specific overload // based on the function name and the .mangleof of its argument // types. The key to this trick is that the .mangleof of a // template encodes its argument types, so it is unique per // combination of argument types. template FuncSignature(string funcName, ArgTypes...) { enum FuncSignature = funcName ~ ArgTypesWrapper.mangleof; } class Mock(... /* whatever you currently have here */) { // This unfortunately has to be a template function in // order to be able to capture the argument types of the // delegate in the typetuple A. This may complicate the // implementation of how you'd actually dispatch to the // overload implementation at runtime. void addMethod(R, A...)(string funcName, R delegate(A...) dg) { string overloadName = FuncSignature!(funcName, A); // Now overloadName should be a unique string // representing that particular combination of // function name and argument types, i.e., it's // a function signature. So you can use it to // identify which overload is which. } } T
Sep 12 2013