digitalmars.D.learn - Getting and using class hierarhy information in runtime
- Uranuz (26/26) Feb 13 2014 In my web application on D I want to implement some type of
- Adam D. Ruppe (18/20) Feb 13 2014 The easiest way is to simply use cast:
- Uranuz (4/10) Feb 13 2014 Yes. I was thinking about this but I want some more "clear
- Uranuz (44/44) Feb 13 2014 I suddenly posted unfinished message.
- Adam D. Ruppe (32/33) Feb 13 2014 This function is basically the same as the cast function in
In my web application on D I want to implement some type of "event based error handling". I'm process some events of request handler with some wodified version of this: http://code.dlang.org/packages/std_event I'm trying to implement error handling in event "onError". I pass Throwable object as parameter to it. But I want to have these events to be sepearted by type so I will attach different handlers for different error types at runtime manner as in .NET platform. Problem is that I need at first handle "more specialized" types of events that inherited from other less specialized types. Is it possible to check somehow at runtime that one object inherits from another object somehow using .classinfo property. I'll try to give an example of what I want. It's may be not correct D code. class BaseHTTPException: Exception {} class SpecializedHTTPException: Exception {} alias bool function(Throwable error) ErrorHandler; class RequestHandler { private: ErrorHandler[][TypeInfo_Class] _errorHandlers; } void main()
Feb 13 2014
The easiest way is to simply use cast: Exception e = ...; if(auto b = cast(BaseHTTPException) e) { // use b of that type } else if(auto s = cast(SpecializedHTTPException) e) { // use s, e is of this type } and so on. On Friday, 14 February 2014 at 03:37:16 UTC, Uranuz wrote:Is it possible to check somehow at runtime that one object inherits from another object somehow using .classinfo property.classinfo also includes members for base class and a list of interfaces (in fact, internally, this is how the dynamic cast operator is implemented - it walks these chains and keeps track of the appropriate offset to convert the object). But the cast will probably do what you need in a simpler way. Also btw, the .classinfo and/or the typeid(obj) expressions will go straight to the most derived type. If you use that, you should be able to go into your associative array of handlers directly. But that won't call it for base classes so pros and cons.
Feb 13 2014
Yes. I was thinking about this but I want some more "clear looking" way of attaching handlers for errors, because I could have a lot of them and using a lot of if operators is not good for me.Exception e = ...; if(auto b = cast(BaseHTTPException) e) { // use b of that type } else if(auto s = cast(SpecializedHTTPException) e) { // use s, e is of this type }
Feb 13 2014
I suddenly posted unfinished message. In my web application on D I want to implement some type of "event based error handling". I'm process some events of request handler with some wodified version of this: http://code.dlang.org/packages/std_event I'm trying to implement error handling in event "onError". I pass Throwable object as parameter to it. But I want to have these events to be sepearted by type so I will attach different handlers for different error types at runtime manner as in .NET platform. Problem is that I need at first handle "more specialized" types of events that inherited from other less specialized types. Is it possible to check somehow at runtime that one object inherits from another object somehow using .classinfo property. I'll try to give an example of what I want. It's may be not correct D code. class BaseHTTPException: Exception {} class SpecializedHTTPException: Exception {} alias bool function(Throwable error) ErrorHandler; class RequestHandler { void processRequest(string msg) { try { ///Doing some processing on msg } catch(Throwable exc) { foreach( type, hdl; _errorHandlers ) { if( exc.inheritsOrIs(type) ) //Checking type of exception { if( hdl(exc) ) { return; //Error handled } } } } } private: ErrorHandler[TypeInfo_Class] _errorHandlers; } Or may you would advise some other less complicated way.
Feb 13 2014
On Friday, 14 February 2014 at 03:48:13 UTC, Uranuz wrote:{ if( exc.inheritsOrIs(type) ) //Checking type ofThis function is basically the same as the cast function in druntime. Look for _d_isbaseof in the file dmd2/src/druntime/src/rt https://github.com/D-Programming-Language/druntime/blob/master/src/rt/cast_.d#L115 You could literally call that function: class Foo {} class Bar : Foo {} class Baz : Bar {} class Test {} // declare the function so we can access it (as an internal druntime // function, thee is no import to provide it, but we can call it anyway) extern(C) int _d_isbaseof(ClassInfo oc, ClassInfo c); void main() { Foo f = new Bar; Foo z = new Baz; import std.stdio; // here's how to use it. f is a Bar which is a Foo, but not a Baz writeln(typeid(f)._d_isbaseof(typeid(Bar))); // 1 writeln(typeid(f)._d_isbaseof(typeid(Baz))); // 0 writeln(typeid(f)._d_isbaseof(typeid(Test))); // 0 // z is a Baz which is a Bar and a Baz writeln(typeid(z)._d_isbaseof(typeid(Bar))); // 1 writeln(typeid(z)._d_isbaseof(typeid(Baz))); // 1 } typeid is the same as classinfo, it just gets that info. So the left side in your case would be the exception, and the right side would be the key in your associative array. If it returns one, you have a match and can do ahead and call it.
Feb 13 2014
// declare the function so we can access it (as an internal druntime // function, thee is no import to provide it, but we can call it anyway) extern(C) int _d_isbaseof(ClassInfo oc, ClassInfo c);Maybe implementing such functionality somewhere as standart function or method would be a a god idea. It could be a method TypeInfo_class object or as stand alone function in phobos library. I think that I'm not the first who is searching for short and clear way for determining inheritance relation between object at runtime.
Feb 14 2014
Also I have the following code but I get some error. I think it's because of std.algorithm.sort function that uses mixin to inject predcate. But it doesn't import symbols passed in predicate and fails. Is there some way of resolving this problem or I need to inject full code of function inside predicate? import std.stdio, std.algorithm; class A: Exception { this(){ super(null); } } class B: A {} class C: B {} class D: A {} class E: A {} class F: E {} size_t countDerivations(TypeInfo_Class typeinfo) { size_t result; while(typeinfo !is null) { //writeln(typeinfo.name); result ++; typeinfo = typeinfo.base; } return result; } void main() { auto typeinfo = typeid(C); //while(typeinfo !is typeid(Throwable)) //{ writeln(typeinfo.name); // typeinfo = typeinfo.base; //} auto list = [ typeid(C), typeid(B), typeid(A), typeid(F) ]; //writeln( countDerivations( typeid(C) ) ); auto sortedList = sort!("countDerivations(a) > countDerivations(b)")( list ); writeln(sortedList); }
Feb 14 2014
I solved it myself. I forget that I can use function as predicate import std.stdio, std.algorithm; class A: Exception { this(){ super(null); } } class B: A {} class C: B {} class D: A {} class E: A {} class F: E {} size_t countDerivations(TypeInfo_Class typeinfo) { size_t result; while(typeinfo !is null) { //writeln(typeinfo.name); result ++; typeinfo = typeinfo.base; } return result; } void main() { auto typeinfo = typeid(C); //while(typeinfo !is typeid(Throwable)) //{ writeln(typeinfo.name); // typeinfo = typeinfo.base; //} auto list = [ typeid(C), typeid(B), typeid(A), typeid(F) ]; //writeln( countDerivations( typeid(C) ) ); auto sortedList = sort!( (a, b) { return countDerivations(a) > countDerivations(b); } )( list ); writeln(sortedList); }
Feb 14 2014