www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting and using class hierarhy information in runtime

reply "Uranuz" <neuranuz gmail.com> writes:
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
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
parent "Uranuz" <neuranuz gmail.com> writes:
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
prev sibling parent reply "Uranuz" <neuranuz gmail.com> writes:
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
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 14 February 2014 at 03:48:13 UTC, Uranuz wrote:
        {   if( exc.inheritsOrIs(type) )  //Checking type of
This 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
parent reply "Uranuz" <neuranuz gmail.com> writes:
 // 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
parent reply "Uranuz" <neuranuz gmail.com> writes:
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
parent "Uranuz" <neuranuz gmail.com> writes:
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