332 lines · 8.9 KB · C++
RawDownload
//// (c) 2002-2003, sof.//// Dynamic invocation helper classes. The details of how// to access the .NET object model via the Reflection API// is taken care of by Invoker.{h,cpp}//#include "Invoker.h" namespace DynInvoke { static TypeName* ParseType(String* str) {    int curPos = 0;    int endPos;     //    Console::WriteLine("x{0}y", str);    TypeName* typeName = new TypeName();     if ( str->get_Chars(0) == '[' ) {      endPos = str->IndexOf(']');      curPos = endPos + 1;      typeName->m_assembly = str->Substring(1,endPos-1);      typeName->m_length = endPos+1;    }    String* delimStr = " ,()";    Char delims __gc [] = delimStr->ToCharArray();     endPos  = str->IndexOfAny(delims,curPos);    //    Console::WriteLine("{0} {1} x{2}x", __box(endPos), __box(curPos), str);    if ( endPos == -1 ) {      typeName->m_class = str->Substring(curPos);    } else {      typeName->m_class = str->Substring(curPos,endPos-curPos);    }     //    typeName->m_class = str->Substring(curPos,endPos-curPos);    typeName->m_length += endPos-curPos;     return typeName;} // Method: GetType(String* typeName);// // Purpose: Assembly-savvy version of Type::GetType()//Type* InvokeBridge::GetType(String* typeName) {   try {    Type* t = Type::GetType(typeName);    if (t) return t;  } catch (Exception*) {    ;  }   for (int i=0;i < InvokeBridge::m_assemblies->Count; i++) {     try {       String* stuff = String::Format("{0},{1}",typeName,InvokeBridge::m_assemblies->get_Item(i)->ToString());       //       Console::WriteLine(stuff);       Type* t = Type::GetType(stuff);       if (t) {	 return t;       }     } catch (Exception*) {       continue;     }  }  return 0;} //// Method:  CreateInstance(String* typeName, Object* [])//// Purpose: Assembly-savvy invocation of Activator::CreateInstanceObject* InvokeBridge::CreateInstance(TypeName* typeName,				     Object* args[]) {   Object* instance = 0;  Type*   t = InvokeBridge::GetType(typeName->toStdString());   //  Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);  if (!t) {    try {      Assembly* localA = Assembly::LoadFrom(typeName->m_assembly);      t = localA->GetType(typeName->m_class);    } catch (Exception* e) {      ;    }  }    if (!t) {    try {      AppDomain* currentDomain = AppDomain::CurrentDomain;            //      Assembly* stuff[] = currentDomain->GetAssemblies();      //      for (int i=0;i < stuff.Length; i++) {      //	Console::WriteLine("x{0} y{1}", stuff[i]->ToString(), stuff[i]->FullName);      //      }      //      Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);      Assembly* localA = Assembly::LoadWithPartialName("HugsAssembly");      t = localA->GetType(typeName->m_class);      //      Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);    } catch (Exception*) {      ;    }  }   if (t) {    try {      Object* o =Activator::CreateInstance(t,(Object* [])args);      return o;    } catch (Exception* e) {      Console::WriteLine("Failure: {0}", e);      return 0;    }  }} //// Method: CreateObject(String* objSpec, Array* args)//// Purpose: Given a fully qualified name of a class/type, try//          to create an instance of it.//Object* InvokeBridge::CreateObject(String* assemName,				   String* objSpec,				   Array* args) {   Object* instance = 0;   // Unravel the name of the class/type.  TypeName* typeName = ParseType(objSpec);    if (assemName != 0 && assemName->Length > 0) {    typeName->m_assembly = assemName;  }   // Try creating the instance..  try {    instance = InvokeBridge::CreateInstance(typeName,(Object* [])args);  } catch (Exception* e) {    Console::WriteLine("Unable to create instance \"{0}\" {1}", objSpec, e);    throw(e);  }  if (!instance) {    Console::WriteLine("Unable to create instance \"{0}\"", objSpec);  }  return instance;} //// Method:  InvokeMethod// // Purpose: Given a pointer to an already created object, look up//          one of its method. If found, invoke the method passing it//          'args' as arguments.//Object*InvokeBridge::InvokeMethod(Object* obj, 			   String* methName,			   Array* args) {  // Get the methods from the type  MethodInfo* methods __gc[] = obj->GetType()->GetMethods();  MethodInfo* mInfo;   if (!methods) {    Console::WriteLine("InvokeMethod: No matching types found");    return 0;  }			  System::Reflection::BindingFlags flgs     = (System::Reflection::BindingFlags) // why do I need to cast?      (System::Reflection::BindingFlags::Public       |       System::Reflection::BindingFlags::NonPublic    |       System::Reflection::BindingFlags::Instance     |       System::Reflection::BindingFlags::Static       |       System::Reflection::BindingFlags::InvokeMethod);      /* Caller is assumed to catch any exceptions raised. */  return obj->GetType()->InvokeMember(methName,				      flgs,				      0,				      obj,				      (Object __gc* [])args);} //// Method:  InvokeStaticMethod// // Purpose: Invoke a static method, given the fully qualified name//          of the method (and its arguments). If found, invoke the//          method passing it 'args' as arguments.//Object* InvokeBridge::InvokeStaticMethod(String* assemName,					 String* typeAndMethName,					 Array* args) {   // Get the methods from the type  MethodInfo* methods __gc[];  MethodInfo* mInfo;   int lastDot = typeAndMethName->LastIndexOf('.');  String* className = typeAndMethName->Substring(0,lastDot);  String* methName  = typeAndMethName->Substring(lastDot+1);   // Unravel the name of the class/type.  TypeName* typeName = ParseType(className);  Type* t;    if (assemName != 0 && assemName->Length > 0) {    typeName->m_assembly = assemName;  }    try {    t = InvokeBridge::GetType(typeName->toStdString());        if (!t) {      try {	Assembly* localA = Assembly::LoadFrom(typeName->m_assembly);	t = localA->GetType(typeName->m_class);	//	Console::WriteLine("InvokeStaticMethod: Type {0} found", t);      } catch (Exception* e) {	;      }    }     if (t) {      methods = t->GetMethods();    } else {      Console::WriteLine("InvokeStaticMethod: Type {0} not found", className);      return 0;    }  } catch (Exception *e) {      Console::WriteLine("InvokeStaticMethod: Type {0} not found", className);      throw(e);  }   System::Reflection::BindingFlags flgs     = (System::Reflection::BindingFlags) // why do I need to cast?      (System::Reflection::BindingFlags::DeclaredOnly |       System::Reflection::BindingFlags::Public       |       System::Reflection::BindingFlags::NonPublic    |       System::Reflection::BindingFlags::Static       |       System::Reflection::BindingFlags::InvokeMethod);      return t->InvokeMember(methName,			 flgs,			 0,			 0,			 (Object __gc* [])args);} //// Method:  GetField//// Purpose: Fetch the (boxed) value of named field of a given object.//Object* InvokeBridge::GetField(Object* obj, System::String* fieldName) {   FieldInfo* fInfo = obj->GetType()->GetField(fieldName);  return fInfo->GetValue(obj);} //// Method:  GetStaticField//// Purpose: Fetch the (boxed) value of named static field.//Object* InvokeBridge::GetStaticField(System::String* clsName,				     System::String* fieldName) {   Type* ty = InvokeBridge::GetType(clsName);  System::Reflection::BindingFlags static_field_flgs     = (System::Reflection::BindingFlags)    (System::Reflection::BindingFlags::Public       |     System::Reflection::BindingFlags::NonPublic    |     System::Reflection::BindingFlags::FlattenHierarchy |     System::Reflection::BindingFlags::Static);   FieldInfo* fInfo = ty->GetField(fieldName, static_field_flgs);  return fInfo->GetValue(0); // according to doc, ok to pass any val here.} //// Method:  SetField//// Purpose: Replace the (boxed) value of named field of a given object.//void InvokeBridge::SetField(Object* obj, System::String* fieldName, Object* val) {   FieldInfo* fInfo = obj->GetType()->GetField(fieldName);  fInfo->SetValue(obj,val);  return;} //// Method:  SetStaticField//// Purpose: Replace the (boxed) value of named static field.//void InvokeBridge::SetStaticField(System::String* clsName,				  System::String* fieldName,				  Object* val) {   Type* ty = InvokeBridge::GetType(clsName);  System::Reflection::BindingFlags static_field_flgs     = (System::Reflection::BindingFlags)    (System::Reflection::BindingFlags::Public       |     System::Reflection::BindingFlags::NonPublic    |     System::Reflection::BindingFlags::FlattenHierarchy |     System::Reflection::BindingFlags::Static);    FieldInfo* fInfo = ty->GetField(fieldName,static_field_flgs);  fInfo->SetValue(0,val);  return;} Array* InvokeBridge::NewArgArray(int sz){ return Array::CreateInstance(__typeof(Object), sz); } void InvokeBridge::SetArg(Array* arr, Object* val, int idx){ arr->SetValue(val,idx);} Object* InvokeBridge::GetArg(Array* arr, int idx){ return arr->GetValue(idx);} } /* namespace */