3

I have written a fairly simple app that is a MDI windows form. I dynamically build menu items for the different forms that will be loaded. On the click even of the menu items, I call a method called ShowForm, passing in the form name as a string. I then attempt to open the form using the following code:

Dim strFullname As String = Application.ProductName & ".frm" & strFormName
Dim typForm As Type = Type.GetType(strFullname, True, True)
Dim CSFEMDIChild As Form = CType(Activator.CreateInstance(typForm), Form)

I get the following error executing the second line:

Could not load type 'MyAssemblyName.frmInquiryEntry' from assembly 'MyAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'

I have read other questions related to this error, but most of them have references to custom assemblies. I have looked in the GAC, but I don't see any assembly that seems related to this app. I have cleared bin/x86/debug so it would recreate all of those items. I don't even have any references in this project beyond the default ones. Any ideas?

djv
  • 15,168
  • 7
  • 48
  • 72
Doug Sholly
  • 123
  • 1
  • 10
  • `frmInquiryEntry` is a form that you created yourself, in the same project? – Bradley Uffner Apr 13 '17 at 17:46
  • Yes, that is correct. – Doug Sholly Apr 13 '17 at 17:54
  • 2
    The TypeName for that overload of `GetType` expects an "Assembly Qualified Name", which has a special format. See this [documentation](https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname%28v=vs.95%29.aspx?f=255&MSPPError=-2147217396) on how to construct one. – Bradley Uffner Apr 13 '17 at 17:59
  • Another option is to get the reference to the `Type` from the `Assembly`, rather than from `Type.GetType`. If the class is in the same assembly as the executing code you can just do `Assembly.GetExecutingAssembly.GetType`, which just needs the "full type name" of the type, rather than the "assembly qualified name". I think your original method of constructing the type name will work for that. – Bradley Uffner Apr 13 '17 at 18:16
  • I gave your second suggestion a try, and I do not have an error anymore, but I am getting `Nothing` when executing `Dim typForm As Type = Assembly.GetExecutingAssembly.GetType(strFullname)` I am using the same code above for constructing strFullName. Maybe `strFullname` is still malformed? – Doug Sholly Apr 13 '17 at 19:01
  • Sounds like it. That easiest way to see the name would be to reference the type explicitly, as in `Debug.WriteLine(GetType(frmInquiryEntry).FullName)`, which should output the exact fully qualified name that you can use. `AssemblyQualifiedName` would also give you the string to use for your original method. – Bradley Uffner Apr 13 '17 at 19:47

1 Answers1

1

A simple mcve works just fine with a winforms project with Form1 and Form2 and your code in Form1, but with

Dim strFullname As String = Application.ProductName & ".Form2"

So what's different? Most likely it's a Namespace issue. For example, if Form2 is defined in namespace Foo, then the above code fails, but this works

Dim strFullname As String = Application.ProductName & ".Foo.Form2"

Actually, the Application.ProductName in your case is taking place of the root namespace. In my examples, WindowsApplication1 and WindowsApplication1.Foo are the namespaces, respectively.

So you need to include the Namespace, if you know it.

In my example, the current Namespace (in which the Form is defined) can be found and used

Dim currentNamespace = GetType(Form1).Namespace
Dim strFullname As String = currentNamespace & ".Foo.Form2"

and happens to be the same as the assembly name, by default

enter image description here

but chances are you have defined your child forms in another Namespace. If this is the case, it might be prudent to create a form loader factory with a setting which holds the Namespace.

djv
  • 15,168
  • 7
  • 48
  • 72
  • My actual assembly name is `AdQIC Dashboard` and my Root Namespace is `AdQIC_Dashboard`. When i replaced `Application.ProductName` (which produced `AdQIC Dashboard` ) with `AdQIC_Dashboard`, 2 of the forms now work exactly like I expected, but a 3rd (the original form created in the project, the other 2 were added later) does not work with either string. How do I determine what namespace these forms were created in? – Doug Sholly Apr 14 '17 at 12:28
  • Wait, never mind. I misspelled the name of the 3rd form which is why the gettype was returning nothing. I am marking this as the answer. This also solved the loading of the assembly error when I returned to the original code. I am assuming the reason `Application.ProductName` worked in the examples I found was because their `Assembly Name` and their `Root Namespace` were the same. As a side note, is there a method that returns the Root Namespace so I don't have to hard code that string? Oh, and thanks for the help! – Doug Sholly Apr 14 '17 at 12:42
  • Not really, see http://stackoverflow.com/a/96343/832052. Like I said, you could make a form loader factory with a setting for your namespace. Setting could be stored in application settings or xml file or similar. – djv Apr 14 '17 at 16:22