.NET Forum / Visual Studio.NET / IDE / May 2006
IDesignerHost.GetType()
|
|
Thread rating:  |
Mark Olbert - 20 Apr 2006 15:59 GMT I originally posted this over in the base Framework forum, but the MS folks there said that IDesignerHost is implemented by Visual Studio, so I thought I'd post the questions here to see if anyone can answer them.
Here's an example of a solution that demonstrates, conceptually, some questions/issues with IDesignerHost.GetType():
ProjectA (assembly name AssemblyA): ComponentA
ProjectB (assembly name AssemblyB): references ProjectA ComponentB CustomDesignerB (for ComponentB)
Within CustomDesignerB, you would expect to have to call IDesignerHost.GetType("ProjectA.ComponentA, AssemblyA") in order to create a Type representing ProjectA.ComponentA.
Calling IDesignerHost.GetType("ProjectA.ComponentA") works just as well. In fact, from a little bit of testing it appears that you never have to specify the assembly in the IDesignerHost.GetType() call, provided the Type you're creating is defined in an assembly referenced in ProjectB.
That's sort of understandable: whatever routine searches for the metadata used to create a Type probably starts by looking in the current project (ProjectB, in my example) and the assemblies it references.
But what's really weird is that IDesignerHost.GetType("ProjectA.ComponentA, AssemblyB") works just as well. Apparently, if the metadata search can find the information it needs from the Type name, minus the assembly add-on, it ignores the assembly add-on.
I discovered this by accident; I meant to do the call as IDesignerHost.GetType("ProjectA.ComponentA, AssemblyA"), but goofed up.
At this point my main interest is in understanding how IDesignerHost.GetType() does its work, since it looks like what I need, but the documentation on it is pretty sparse. I like that it can create Types at design-time which are defined in the source code of the project I'm building (I need that capability in some of my custom designers and UITypeEditors). But I'd like to know more details, so I can see if it may cause some problems for me down the road.
Do you have access to any information on the "guts" of how IDesignerHost.GetType() works, and how it differs from Type.GetType()? They do behave differently!
In my example, calling Type.GetType("ProjectA.ComponentA, AssemblyA") or Type.GetType("ProjectA.ComponentA") within CustomDesignerB returns a null...unless you first call IDesignerHost.GetType(), after which Type.GetType() works just fine. I presume that means IDesignerHost.GetType() is loading metadata from the current project someplace where Type.GetType() can access it, but that Type.GetType() isn't smart enough to do that load itself.
- Mark
Steven Cheng[MSFT] - 21 Apr 2006 07:40 GMT Hi Mark,
Thank you for posting.
Glat that you've made further progress on this. As for the IDesignerHost interface, the concrete implemention for VS IDE is the System.ComponentModel.Design.DesignerHost class, and the GetType method of this class internally query another design-time interface, "ITypeResolutionService" and call this interface's GetType method. And for VS IDE, the detailed implemenation on this interface is a pure VS IDE specific one , named "VsItemTypeResolutionService", which is in the Microsoft.VisualStudio.Web.dll assembly. Based on my inspecting on the type (if you have interesting, we can check the code logic through the reflector tool)'s GetType method, it is AssemblyName sensitive, so if we passed a wrong assemblyName in the Type Name, it will return Null. I've tested this in my local projects. Actually the detailed code logic of the type searching is like below:
1. check the type name to see whether it is assemblyname qualified:
2. If assembly named qualified, first check the cachedTypes through the full typename, if not exists, type load the type from the specific assemby....
3. If not assembly name qualified, also check Type CAche first, then, check all the available assemblies one by one ....
So I'm also feeling a bit strange that it return the type instance regardless of the wrong assembly name. Anyway, such detailed codelogic is always encapsulated and hidden from the users(through abstract interface).
Hope this helps.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Mark Olbert - 24 Apr 2006 04:00 GMT Steven,
(This still refers to my earlier extended example).
I am pulling my hair on getting this design time Type/run time Type stuff to work properly! IDesignerHost.GetType() won't work if I pass it an assembly-qualified name. It only works if I pass it a Type name without any assembly name...and it won't work all the time then, either. But at runtime, Type.GetType() won't work without the assembly-qualified name!
Can you please explain to me what's going on? What are the specific rules for declaring a Type name so that it can be created at design time via IDesignerHost.GetType() and at run time via Type.GetType()?
- Mark
Steven Cheng[MSFT] - 24 Apr 2006 12:01 GMT Thank you for the response Mark,
The IDesignerHost.GetType method can accept assemblyQualifiedname for the typeName. There must be something else cause it fail to get the t ype. Are you using the code(or the editor) it in ASP.NET project or winform project? For winform project, the project will have a default namespace and assembly Name setting for the main assembly compiled for the project, so we can use it as the assembly name passed to the GetType method's typename parameter. For type in class library, I think we can always correctly get the type instance through IDesignerHost.GetType with AssemblyQualifiedname, yes?
For ASP.NET project(2.0), it is a bit different, since there is no precompiled assembly, and no fixed assembly name setting in project. However, the ASP.NET provide two keyword to let us use to represent the ASP.NET dynamic compiled assembly (for types in the application, e.g in App_Code folder). The two keywords are "App_Code" and "__code". So for a certain custom type in App_Code folder. e.g a class named TestObjectClass, we can use the following AssemblyQualifiedName to reference it:
"TestObjectClass, __code"
or "TestObjectClass, App_Code"
and if we do not provide assembly name, the IDE will search all the available referenced assemblies for that type(also include the current project itself.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Steven Cheng[MSFT] - 27 Apr 2006 13:10 GMT Hi Mark,
How are you doing on this? Does the further info in my last reply helps some? If still anything we can help, please feel free to post here.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Mark Olbert - 27 Apr 2006 17:06 GMT Steven,
It was helpful, thanks. However, I'm still wrestling with an oddity (which I think won't be a problem when I release the product I'm working on, and has a workaround during development).
I have a solution which contains a number of wizard libraries (i.e., one for each custom wizard), which are then loaded at startup by an application. Each of the wizard libraries relies on a base wizard library. When I debug the base wizard library using a separate instance of VS2005 (which is working on the solution with the multiple wizard libraries) I get some odd effects with IDesignHost.GetType(). Here's a text diagram of the situation:
First instance of VS2005: Solution: BaseWizardLibrary Project: BaseWizardProject defines a BaseWizard class debug this library using the "multilibrary" solution
Second instance of VS2005 Solution: MultiWizardApplication Project1: references BaseWizardLibrary defines CustomWizard1, derived from BaseWizard Project2: references BaseWizardLibrary defines CustomWizard2, derived from BaseWizard ... ProjectApp: references Project1, Project2, etc.
If I make a change to the BaseWizardLibrary, launch a second instance of VS2005 on the MultiWizardApplication, and call IDesignerHost.GetType() from within the designer of one of the custom wizards, I get back a Type, but it is not considered to be derived from BaseWizard (even though it is).
I thought this was odd, so I added the following to the designer code (the designer is defined in the BaseWizard assembly): Type junk = typeof(BaseWizard);
When the debugger hits this line there's an error thrown (resulting in a null value being returned). The message says something about BaseWizard being defined in two different assemblies (two different GUID-like values are contained in the error message).
The workaround I've found is this: whenever I make a change to the BaseWizard solution, always do a full compile of the MultiWizardApplication before opening one of the designers on a wizard in the MultiWizardApplication. Apparently, VS2005 only updates the reference to the BaseWizardLibrary in the active project of the MultiWizardApplication solution when VS2005 starts up. You have to do a full compile to get the other references updated (and if you don't do that, you have stale versions of the BaseWizardLibrary lying around the solution, causing the problem).
Are you familiar with this behavior?
- Mark
Steven Cheng[MSFT] - 01 May 2006 12:14 GMT Thanks for the followup Mark.
Glad to be of assistance. As for the further problem you mentioned, I'd like to think it as the cache of the IDE since for those types which are under designing, it could be changed, and when the designer get loaded, only a certain version of the type/assembly is loaded. So if we make further changes, the designerview may not get refreshed immediately. In addition to the doing full compilation on all the projects in solution, you can also try close the designer and reopen it after any referenced dependent projects assemblies get updated and recompiled. Anyway, this does coupled with the internal code logic, I also haven't thorough view over the exact implementation.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|