Thursday, December 29, 2005

The invoked member is not supported in a dynamic assembly.

You might encounter another issue with the forms designer in Visual Studio 2005. When you have located a user control on the form, and the user control is in a different project, and the user control uses GetExportedTypes() to determine visible types, then you might receive the following error message when trying to view the form:
The invoked member is not supported in a dynamic assembly.
The error message is typically accompanied with a stack dump including information about the line of code which causes the problem. In order to solve the issue you need to find a different way of coding. In my case I had to use GetTypes() instead of GetExportedTypes(). After that change the form designer worked again as expected.

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Sometimes when working with a solution containing multiple projects, with several forms some of them containing user controls, Visual Studio .NET 2005 produces the following error when you try to open the form in the form designer:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
In some cases the following approach helps solving this issue:
  1. Close the form designer
  2. Close the solution and Visual Studio
  3. From the project that contains the problematic form delete the bin and the obj folder
  4. Start Visual Studio again and load your solution
  5. Rebuild the solution
  6. Reload the form
Not nice, but at least it's a workaround. I don't know yet how to reproduce the issue, but it seems to be related to user controls in one project which are used in a form in a different project.

Wednesday, December 28, 2005

User Control in Tool Window of a Visual Studio Addin

Visual Studio .NET 2005 offers some new APIs for making it easier to host a managed add-in. For instance, the function CreateToolWindow2() allows hosting a custom control within a tool window. A shim control is no longer necessary. The function call might look like this:
_toolWindow = toolWins.CreateToolWindow2(
   _addInInstance,
   asmPath,
   ctlProgId,
   "AgileTest",
   guidString,
   ref objTemp);
The documentation states that the objTemp parameter will contain a reference to the user control hosted in the new tool window. With my experiments so far I have never found that variable to be anything other than null. In order to get a reference to my hosted user control I therefore used a different approach. First I defined an event on the class level for the user control like this:
public static event EventHandler ControlCreated;

private void AgileTestHostCtrl_Load(object sender, EventArgs e) {
   if(ControlCreated != null) {
      ControlCreated(this, null);
   }
}
For this event I defined an event handler in the Connect class of the add-in:
void AgileTestCtrl_ControlCreated(object sender, EventArgs e) {
   _hostedControl = (AgileTestCtrl)sender;
}
Registering the handler on a class level event is easy:
AgileTestCtrls.AgileTestCtrl.ControlCreated += 
   new EventHandler(AgileTestCtrl_ControlCreated);
Now when the user control is loaded the event is fired, and the event handler is called. The limitation of this solution is obviously that should you need several instances of the same tool window it might get more complicated to distinguish between them. One option to solve this might be to use an event that carries additional information in its properties. In my case as I don't need more than one instance of the tool window and hence of my user control, this solution works fine and reliable. Please drop me a note if you are aware of a better solution. Thank you!

Wednesday, December 21, 2005

This is about DotNet

This blog is about DotNet. I'm a founding member of the csUnit team. In this blog I'd like to focus on general and special .NET 2.0 questions. Feedback is most certainly welcome!