Loadfrom and CreateInstance failed in Beta2
I have a window application that loads dll from a remote server at runtime using the Assembly.LoadFrom() function. The code looks like this:
| | try { //download and load the assembly downloadedAssembly = System.Reflection.Assembly.LoadFrom(url); // find the type in the assembly for the object we want to create formType = downloadedAssembly.GetType(type); //Create an instance of the desired type and show it downloadedForm = System.Activator.CreateInstance(formType); } catch (Exception exc) { m_log.Error(string.Format("LoadAssembly failed. {0}", exc.ToString())); string msg = "Failed to download assembly from url: " + url + "\n" + exc.Message; MessageBox.Show(msg, "ConfigTool", MessageBoxButtons.OK, MessageBoxIcon.Error); }
|
formType is derived from
| | class A : UserControl, ITools { A(); .... }publicinterface ITools { void SetCTMgr(CTManager mgr); void SetDirty(bool bDirty); void ExitCtrl(); ..... }
|
This used to work fine in Beta 1 but I got an exception in Beta2 from Activator.CreateInstance: "Exception has been thrown by the target of an invocation.". From the debugger, I check the properties of formType and the only properties that look suspicious are: -DeclaringMethod: Method may only be called on a Type for which Type.IsGenericParameter is true.
- GenericParamterAttritbutes: Method may only be called on a Type for which Type.IsGenericParameter is true.
- GenericParamterPosition: Method may only be called on a Type for which Type.IsGenericParameter is true.Anyone have any clue what is wrong? Thanks alot!
[2772 byte] By [
kpoon] at [2007-12-16]
The exception that is being thrown is a TargetInvocationException, this exception is typically thrown when a constructor or method called via Reflection (ie Activator.CreateInstance) throws an exception. The exception thrown by the user code is wrapped by the TargetInvocationException.
What you need to do is something like this:
| |
try { ... } catch (TargetInvocationException ex) { MessageBox.Show(ex.InnerException.Message); }
|
Thanks for the reply! I wrote a simple version of my application and tested it with catching the TargetInvocationException. Here is a brief description of the reference structure of the application. Sorry for the long description. I don't see an option to attach zip file here. So, here it is:
- Project WindowApplication2 is a simple window application contains one form with one button. When the button is clicked, it calls LoadFrom(url), GetType(), and CreateInstance(),etc to load WindowsControlLibrary1.dll and instantiate UserControl1. Here is where I catch the TargetInvocationException.
- WindowsControlLibrary1.dll contains only 1 UserControl1 which derived from UserControll. UserControl1 also contains a MyTextBox object defined in ClassLibrary1.dll. So WindowsControlLibrary1.dll has reference to ClassLibrary1.dll.
- ClassLibrary1.dll only contains a simple MyTextBox class which derived from TextBox.
So the dependency picture would be like:
WindowsApplication2 -> WindowsControlLibrary1->ClassLibrary1
When I run the app and click the button to load the UserControl1 from WindowsControlLibrary1.dll, I got the "Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies." error message. I check ClassLibrary1.dll is at the right location along with WindowsControlLibrary1.dll in the web server and ClassLibrary1 doesn't depends on anything else.
I check the assembly folder for the local cache. It only downladed the WindowsControlLibrary1.dll but not ClassLibrary1.dll. In Beta1, I think LoadFrom() will load all the dependencies from the same location automatically and it seems this is not the case in Beta2. Maybe I missed something? Any idea? Thank you very much!!