Click here to Skip to main content
Click here to Skip to main content

Visual Studio Designer Cache Hell

, 21 Nov 2007
Rate this:
Please Sign up or sign in to vote.
A practical workaround for the "Unable to cast object of type T to type T" error in Visual Studio Designer
Screenshot - DesignerError.jpg

Introduction

If you've ever seen that scary error in your Visual Studio Designer, then you may probably understand me as I thought I'd rather have a break...

When you instantiate an object dynamically using Assembly.Load, and set that object to a property of a UserControl/Form, the designer throws this exception (it seems to be unable to cast an object to its base type or even to its own type!)

Scenario

Say you have a ClassLibrary (VSDCClassLibrary) that contains a type Class1 and an UserControl UserControl1 (in your VSDCControlsLibrary) that has a property Class1Property of type Class1.

When you write an application, you put UserControl1 on a Form and, for some reason, you need to set the Class1Property to an object of type Class2 (derived from Class1) in an assembly (VSCDDerivedClassLibrary) that you can't reference directly.

Screenshot - SolutionExplorer3.jpg

So you switch to "late bound", using Assembly.Load and Assembly.CreateInstance. For example:

private string _class1Path;
public string Class1Path
{
    get { return _class1Path; }
    set 
    { 
        _class1Path = value;
        if (!string.IsNullOrEmpty(value))
        {
            Assembly asm = Assembly.LoadFrom(value);
            Class1Property = (Class1)asm.CreateInstance("VSDCDerivedClassLibrary.Class2");
        }
        else
            Class1Property = null;
    }
}  

If you run the project you'll see it working, as you expected, at runtime. But when you open the Form in the designer...

Explanation

Now we change the startup project to VSDCClassLibrary and set VisualStudio as the startup application. Let's set a breakpoint, open the Form, and have a watch at AppDomain.CurrentDomain.GetAssemblies():

Screenshot - Watch2.jpg

You can see that more copies of the VSDCClassLibrary assembly have been loaded (one for each designer window?) and each time it has a different CodeBase. Only the last instance of your assembly has the original CodeBase, all the others pointing to a fancy path like:

C:\Documents and Settings\<user>\Impostazioni locali\Dati applicazioni
    \Microsoft\VisualStudio\8.0\ProjectAssemblies 

There's where Visual Studio caches Assemblies at design!

When you use Assembly.Load(VSDerivedClassLibrary) from your output (bin) path, the CLR also loads the referenced classlibrary (VSClassLibrary) assembly, that is different to the one in Visual Studio cache, so the cast doesn't work!

You may clear the cache manually, but when you open the designer Visual Studio creates it again.

You may think of using the AssemblyLoad event to get the right assembly, but I can't figure out a way to work out which is the right one!

You may think of putting all binaries in the same directory (it's more consistent and avoids continuous file lock), but that alone does not resolve the problem.

Solution

If you use the byte[] parameter overload of Assembly.Load...

Assembly.Load(File.ReadAllBytes(<yourAssembly.dll>));

... the CLR will not load the referenced assemblies and Visual Studio will use the one it had already loaded from cache.

Finally

  1. You have to use different solutions for libraries and for application. Set the output paths of all projects to the same directory.
  2. Add reference to the binaries of your libraries in your Application projects (yet you do not have the projects in the solution) and set copy local to false.
  3. Use Assembly.Load(File.ReadAllBytes(<yourAssembly.dll>)) at design-time and Assembly.LoadFrom(<your assembly>) (or equivalent) at run time.
Screenshot - DesignerNOError.jpg

Similarly, if you develop a Visual Studio Addin that references your libraries, you have to put the binary in a different directory to the one where you compile your libraries, or you'll get the same problem!

History

  • 21st November, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Attilio Pavone
Web Developer
United States United States
you can find it here

Comments and Discussions

 
GeneralOther solution PinmemberBoochigo28-Jun-09 9:36 
GeneralDifferent context, same problem , other solution PinmemberOrlandoCurioso22-Nov-07 11:17 
GeneralRe: Different context, same problem , other solution PinmemberAttilio Pavone30-Nov-07 5:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 21 Nov 2007
Article Copyright 2007 by Attilio Pavone
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid