January 2006 - Posts

TestPost
This is a test post authored in an amazingly cool super-AJAX application that will kill every other wiki-like engine on earth.
Posting from the freakin' plane!
I'm on my way to Sweden to visit a customer, and I'm writing this post from the freakin' plane!!! Broadband by Boeing... simply amazing... Business trips will never be the same for me...
XLinq: is XML embedded in a host language a good idea or a terrible one?

Note: this entry has moved.

During the MVP Summit, and through various articles and blog posts, Microsoft has been trying to get community feedback on the proposed feature of integrating XML as a first-class concept into a core language (such as VB.NET). It seems so natural, right? After all, they are not the first ones to propose such a thing.
You're dealing with lots XML in your application, what else could you ask than to be able to do something like the following?:

Dim CountriesWithCapital As XElement = _ 
  <Countries> 
    <%= Select <Country Name=(Country.Name) 
                        Density=(Country.Population/Country.Area)> 
                 <Capital> 
                   <Name><%= City.Name %></Name> 
                   <Longitude><%= City.Longitude %></Longtitude> 
                   <Latitude><%= City.Latitude %></Latitude> 
                 </Capital> 
               </Country> _ 
        From Country In Countries, City In Capitals _ 
        Where Country.Name = City.Country %> 
  </Countries>

I see at least a couple drawbacks with this approach:

  1. VS already has a full-featured, very responsive and cool XML editor that includes intellisense powered by schemas, allows XSLT transformation debugging, etc. We would need to have at least an equally capable inline XML editor in place in order to be really productive
  2. Now the “template” for the “rendered” XML is compiled into the application. If I need to change anything about that XML layout, I’ll need to recompile the application.

Of course, this does not mean that we should stick to using XmlWriter and XmlDocument to create XML. That’s just insane and much harder to maintain. But there is another alternative, which I think is better.

Text templating is an old technique. The reason why the syntax above looks so familiar is that it’s mostly classic ASP, and people have been using a similar technique for generating not only XML or HTML, but all kinds of text assets (such as SQL statements). But so far, no general purpose text template rendering engine has been ever been available from Microsoft. Until now.

The DSL tools and GAT come with such an engine code-named T4 (Text Templates Transformation Toolkit, kind of a successor of a previous version code-named T3 which I developed quite some time ago for patterns & practices and bundled in previous versions of GAT). This engine allows you to author very similar XML building code but in a standalone file, that you can later “render” with a given context:

<#@ Template Language="C#" #>
<#@ Property Processor="PropertyProcessor" Name="Customer" #>
 
<?xml version="1.0" encoding="utf-8" ?>
<Customer Name="<# this.Customer.Name #>">
<# foreach (Order order in this.Customer.Orders) { #>
 <Order>
  <Id><#= order.Id #></Id>
  ... etc ...
 </Order>
<# } #>
</Customer>

You can of course choose the language you will use for the template so-called control code, and have properties automatically created by specifying that Property template directive. If you had chosen VB as the language, and were using VB9 runtime/compiler, I suppose nothing would stop you  from having almost *exactly* the same code shown at the beginning. Now, forget about T4, as it’s a tool part of an SDK, probably not well tested outside of the scope it was designed for (code generation at designtime), etc. Imagine if you had such an engine but as part of the .NET framework itself. Imagine you had deep support for intellisense in VS for the control code snippets. There are several benefits to such an approach:

  1. One of the main benefits is that now the language used to author the control code is a “plug-in” to the template editor. This ensures that the template editing experience will be consistent independently of which .NET language you decide to code the control code snippets in. The opposite case happens if you embed the template code (XML in XLinq case) into a host language: all host language editors will need to provide this feature, and we have already started seeing that some .NET languages will support such a feature (probably VB9) whereas others will probably not (most likely C#). Even if they all agree to implement the editor and required language features, third-party languages will still be out of the game unless they spend substantial time adding the feature in a way that is consistent with everyone else’s. In a T4–like approach, pretty much all you would need is a CodeDomProvider.
  2. Given 1., the designers of the template editor will need to design it with pluggability in mind. In fact, this editor will easily become the host for all of the other editors in VS, including the XML editor, SQL editor, C#/VB, ASP.NET, etc. Once this is well done for any one of them, integrating the others will be substantially easier than trying to extend each and every language to support “deep integration” with any of those “languages”.
  3. This will also maximize the productivity of developers that are proficient with this template language. Now they will be able to comfortably generate any target source asset using the same tool.
  4. Mixing the “rendering” code (XML in this case) with the model and controller code makes for poor maintainability. You should think of the XML being generated as a view over a model, resembling very much the MVC pattern. There’s a very interesting paper regarding that. It's already a bit frightening to have the full .NET power at hand inside the template control code... but having it fully intermixed with the M-C code will probably lead to spagethi-like code that we thought we finally got through with ASP.NET. In this regard, I see it as a door for a very likely huge step backwards. (do you really think people will NOT generate HTML or other rendering code with it?)
  5. As the templates themselves can be made to inherit from a given base template class (via an Inherits="MyNamespace.MyBaseClass" attribute on the template directive), you can maximize reuse of control code and rendering helpers, as well as get intellisense driven by this custom base class too (together with whatever the so-called directive processors provide to the template class).
  6. If you take this paradigm further enough, you could even end up with an editor that is much like the ASP.NET one, with custom rendering “controls” which can be templatized (just like in ASP.NET), use binding expression, etc..
  7. Finally, but not less important, is that you can now evolve your “rendered” views without recompiling your entire application. If missed an attribute that is available on the model, but was not needed previously on the rendered/output XML, you can add it simply by changing the template.

I think this is a very interesting area, but I believe Microsoft should strive not to provide another technology that could potentially bring back the nightmares we lived with ASP in the past. If it can be missused, it *will* be missused.

If it were for me, I’d limit the features available on the control code snippets to just control and rendering code: if..else, for/while loops, value retrieval (<#= foo.ToString #>), and that’s it. No object creation, no method calls (as they could have side-effects).

I want an im:// protocol handler installed by [my favorite IM application]

Note: this entry has moved.

I'm SO used to typing WinKey + R, mailto://[address], that I seldom open Outlook's main window to send mails. Even more, Gmail (I don't remember if it was google desktop) can take control of the protocol and open up its compose webpage. 

I started doing the same with Skype calls by using the same combination but with callto://[user] (if only my buddy partner would have a shorter alias instead of callto://victorgarciaaprea ...).

Now I only need im://[hopefully short buddy alias here] (guess which is my partner's :S:S:S).....

And what about post://[my new post title here] to fire-up the default weblog post authoring app? (even if it's openening your blog engine webpage...)

Gmail is DOWN (for the first time for me, and it's been for a while...)

Note: this entry has moved.

I love their attitude upon errors... "Ooops", "Cross your fingers", hahaaa... (luckily I don't run a business on top of this, or it wouldn't be funny at all!!)

How to reuse Windows Workflow Foundation (WF) cool type browser editor in your components

Note: this entry has moved.

Windows Workflow Foundation (WF) comes with a very cool UITypeEditor that allows selection of a type in the current project or any of its references:

Screenshot of WF type browser in action

Its type is System.Workflow.ComponentModel.Design.TypeBrowserEditor defined in the System.Workflow.ComponentModel.dll assembly. However, if you try to "attach" it directly to one of your components properties, you will get an error saying "The service 'System.Workflow.ComponentModel.Compiler.ITypeProvider' must be installed for this operation to suceeed. Ensure that this service is available.":

Screenshot of the error you get when using the WF type browser

Being a general fan of the ComponentModel, I knew what was this about, and started working on providing the WF type browser editor with the services it needs. Here are the implementation steps I used to get it work

  1. It was obvious that I could not use the editor as-is, so the first step was to create a custom UITypeEditor that would call the TypeBrowserEditor in WF:
    public class TypeBrowser : UITypeEditor 

        TypeBrowserEditor editor = new TypeBrowserEditor(); 
        ContextProxy flyweight; 
     
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
        { 
            // Use flyweight pattern to improve performance. It's guaranteed that no more than one instance of  
            // this editor can ever be used at the same time. (it's modal) 
            if (flyweight == null) 
            { 
                flyweight = new ContextProxy(context); 
            } 
            else 
            { 
                flyweight.SetContext(context);     
            } 
     
            return editor.EditValue(flyweight, flyweight, value); 
        } 
     
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext typeDescriptorContext) 
        { 
            return editor.GetEditStyle(typeDescriptorContext); 
        } 
    }
  2. The code highlighted above shows that I'm passing a custom ITypeDescriptorContext to the WF editor. This custom context acts as a proxy to the real one received by the editor, and allows me to provide the additional services required by it. It provides the only service required for the editor to work,  ITypeProvider:
    private class ContextProxy : ITypeDescriptorContext 

        ITypeProvider typeProvider; 
        ITypeDescriptorContext realContext; 
     
        public ContextProxy(ITypeDescriptorContext realContext) 
        { 
            this.realContext = realContext; 
        } 
     
        internal void SetContext(ITypeDescriptorContext realContext) 
        { 
            this.realContext = realContext; 
        } 
     
        #region ITypeDescriptorContext Members 
        ... 
        #endregion 
     
        #region IServiceProvider Members 
     
        public object GetService(Type serviceType) 
        { 
            if (serviceType == typeof(ITypeProvider)) 
            { 
                if (typeProvider == null) typeProvider = new CustomTypeProvider(this); 
     
                return typeProvider; 
            } 
     
            return realContext.GetService(serviceType); 
        } 
     
        #endregion 

  3. The custom ITypeProvider instantiated and returned from the GetService call must give the browser the list of types available in the current project. For that, I took advantage of VS-provided DynamicTypeService and ITypeDiscoveryService, as explained in my previous post:
    private class CustomTypeProvider : ITypeProvider 

        Dictionary<string, Type> availableTypes; 
     
        public CustomTypeProvider(IServiceProvider provider) 
        { 
            DynamicTypeService typeService = (DynamicTypeService)provider.GetService(typeof(DynamicTypeService)); 
            Debug.Assert(typeService != null, "No dynamic type service registered."); 
     
            IVsHierarchy hier = VsHelper.GetCurrentHierarchy(provider); 
            Debug.Assert(hier != null, "No active hierarchy is selected."); 
     
            ITypeDiscoveryService discovery = typeService.GetTypeDiscoveryService(hier); 
            Project dteProject = VsHelper.ToDteProject(hier); 
     
            availableTypes = new Dictionary<string, Type>(); 
            foreach (Type type in discovery.GetTypes(typeof(object), false)) 
            { 
                if (!availableTypes.ContainsKey(type.FullName)) 
                { 
                    if (type.Assembly.GetName().Name != (string)dteProject.Properties.Item("AssemblyName").Value) 
                    { 
                        availableTypes.Add(type.FullName, type); 
                    } 
                    else 
                    { 
                        availableTypes.Add(type.FullName, new ProjectType(type)); 
                    } 
                } 
            } 
        } 


    From that point on, all the ITypeProvider members use the availableTypes field for their implementation. The only caveat was that apparently the WF type browser determines that a type belongs to the current project by the presence of a null value on its Assembly property. However, the VS built-in ITypeDiscoveryService gives you fully loaded types, complete with Assembly property and everything, even for the ones in the current project. Hence, the code above detects if the assembly of a type matches the current and adds to the list a System.Reflection.TypeDelegator-derived class (ProjectType above instead of the real type: 
                        if (type.Assembly.GetName().Name != (string)dteProject.Properties.Item("AssemblyName").Value) 
                        { 
                            availableTypes.Add(type.FullName, type); 
                        } 
                        else 
                        { 
                            availableTypes.Add(type.FullName, new ProjectType(type)); 
                        }
      
    The TypeDelegator class is a not-so-known type that allows a very elegant way to proxy calls to the Type it's delegating to, effectively allowing a kind of reflection interception. This interception is almost transparent, save for the creation of the type delegator with the real Type, as the delegator inherits from Type itself. My delegator is simple, and provides what the WF browser expects: a null value for the Assembly property:
    private class ProjectType : TypeDelegator 

        public ProjectType(Type delegatingType) : base(delegatingType) { } 
     
        public override Assembly Assembly 
        { 
            get { return null; } 
        } 


     So the relevant members of the ITypeProvider interface take into account this trick as follows:
    #region ITypeProvider Members 
     
    public Type GetType(string name, bool throwOnError) 

        if (String.IsNullOrEmpty(name)) 
        { 
            return null; 
        } 
     
        if (availableTypes.ContainsKey(name)) 
        { 
            Type type = availableTypes[name]; 
            if (type is TypeDelegator) 
            { 
                return ((TypeDelegator)type).UnderlyingSystemType; 
            } 
            else 
            { 
                return type; 
            } 
        } 
        else 
        { 
            if (throwOnError) 
            { 
                throw new TypeLoadException(); 
            } 
            else 
            { 
                return null; 
            } 
        } 

     
    public Type GetType(string name) 

        return GetType(name, false); 

     
    public Type[] GetTypes() 

        Type[] result = new Type[availableTypes.Count]; 
        availableTypes.Values.CopyTo(result, 0); 
     
        return result; 

     
    The GetType method is called by the WF browser when you select a type in the listview, and for setting the final return value. So, I achieve the browser requirements for display, but get a fully qualified type name (or the Type itself, depending on the type of the property/value being edited) as an output. 

With that code in-place, you can simply annotate your component members as follows:

public partial class MyComponent : Component 

    public MyComponent() 
    { 
        InitializeComponent(); 
    } 
 
    public MyComponent(IContainer container) 
    { 
        container.Add(this); 
 
        InitializeComponent(); 
    } 
 
    private Type someType; 
 
    [Editor(typeof(TypeBrowser), typeof(UITypeEditor))] 
    public Type DataContractType 
    { 
        get { return someType; } 
        set { someType = value; } 
    } 
}

This could also be a property on a user control, of course. With that simple attribute you can now get the cool WF type editor for your property too:

Screenshot of a working component reusing the WF type browser

In the above screenshot you see:

  • A simple Class Library project containing a component that launches the WF type browser (no need for a WF project!!!)
  • The component we showed previously in source form, being dropped on a WinForm, and its DataContractType property having the "..." for launching the editor
  • The editor with the proper value selected (the one that was already set on the property) as well as the property in the property grid reflecting this value (serialization to code works flawlessly)

What you also see above that I have not explained yet is how to filter the dialog. In the screenshot you see a custom label with the text "Showing types that have DataContractAttribute.", and also from all the types defined in the project or its references, only a few are shown in the treeview/listview. You can achieve this by providing custom filters that implement the ITypeFilterProvider interface. For example, the filter in action above is coded as follows:

public class DataContractFilter : ITypeFilterProvider 

    public DataContractFilter() 
    { 
    } 
 
    public DataContractFilter(IServiceProvider provider) 
    { 
        // Constructor required by the dialog. 
    } 
 
    #region ITypeFilterProvider Members 
 
    public bool CanFilterType(Type type, bool throwOnError) 
    { 
        bool isDataContract = type.IsPublic && Attribute.IsDefined(type, typeof(DataContractAttribute)); 
        if (throwOnError && !isDataContract) 
        { 
            throw new ArgumentException("Type is not a data contract."); 
        } 
 
        return isDataContract; 
    } 
 
    public string FilterDescription 
    { 
        get { return "types that have DataContractAttribute"; } 
    } 
 
    #endregion 

Finally, you apply the filter to your property with another attribute:

 [TypeFilterProvider(typeof(DataContractFilter))] 
[Editor(typeof(TypeBrowser), typeof(UITypeEditor))] 
public Type DataContractType 

It took quite some time and reflectoring, but I'm very satisfied with the result :D
Enjoy!

Update: download the sample code from CodeProject.

XInclude breaks VS 2005 XML editor intellisense

Note: this entry has moved.

A while back I've reported as a bug that VS XML editor breaks if you use XInclude elements in the document. You may ask: "who cares? .NET does not support XInclude anyway!". It just so happens that the recently released version of the Guidance Automation Extensions (GAX) include the Mvp.Xml library, which adds support for XInclude in your guidance package configuration file.

So, in order to benefit from the better manageability and modularity of you guidance package configuration, you have to pay the price of losing intellisense :(... As a workaround, you can keep a dummy XML file around in the solution that you use for authoring the recipe with full intellisense, before you split it in multiple files. However, once you need to start editing it, you're again stuck. I believe the added flexibility is worth the price anyway, but that's just me....(and I'm an XML MVP, so I may be biased ;))

Retrieving available types in current project and its references (withoult locking)

Note: this entry has moved.

One very tricky thing inside VS used to be (at least for me until I found the solution I'm about to show you) to list and work with the types defined in the project as well as its references. The problem was mainly how to properly load the types without locking the project output for compilation, as well as retrieving the types for references that could be also project references. It turns out that there is a very cool and absolutely undocumented service in VS that allows you to do just that, writing no code :)

As a general fan of the System.ComponentModel, I noticed the new System.ComponentModel.Design.ITypeDiscoveryService:

public interface ITypeDiscoveryService
{
     ICollection GetTypes(Type baseType, bool excludeGlobalTypes);
}

Intrigued by the service, I used Reflector's excelent analyze feature to find who uses it. And I got to an interesting one in the VS SDK: Microsoft.VisualStudio.Shell.Design.DynamicTypeService. Among other very interesting members, you can retrieve the aforementioned ITypeDiscoveryService for a given IVsHierarchy:

public ITypeDiscoveryService GetTypeDiscoveryService(IVsHierarchy hierarchy)

(There's also a public ITypeResolutionService GetTypeResolutionService(IVsHierarchy hierarchy) method which should also be very useful)

That looked very promising, and combined with my previous "discovery" of a way to go from a EnvDTE.Project to an IVsHierarchy, it looked like a very easy approach. So here's the code I used:

public Dictionary GetAvailableTypes(IServiceProvider provider, bool includeReferences)
{
     DynamicTypeService typeService = (DynamicTypeService)provider.GetService(typeof(DynamicTypeService));
     Debug.Assert(typeService != null, "No dynamic type service registered.");
 
     IVsHierarchy hier = VsHelper.GetCurrentHierarchy(provider);
     Debug.Assert(hier != null, "No active hierarchy is selected.");
 
     ITypeDiscoveryService discovery = typeService.GetTypeDiscoveryService(hier);
     Project dteProject = VsHelper.ToDteProject(hier);
 
     Dictionary availableTypes = new Dictionary();
     foreach (Type type in discovery.GetTypes(typeof(object), includeReferences))
     {
         // We will never allow non-public types selection, as it's terrible practice.
         if (type.IsPublic)
         {
             if (!availableTypes.ContainsKey(type.FullName))
             {
                 availableTypes.Add(type.FullName, type);
             }
         }
     }

That simple method will give you a dictionary of all the types in the current project as well as its references, without locking any files, and without you having to worry how to traverse the DTE, references, CodeModel, etc. Very cool, indeed :)

Enjoy!

How to get services from the VS DTE (using System.IServiceProvider)

Note: this entry has moved.

VS is heavily based on a component model and container hierarchy of services (yes, that's most probably where System.ComponentModel came from...). Even though there's no comprehensive documentation of all services available and from which contexts, every now and then I find the need to ask for services, but all I've got at hand is either a EnvDTE.ProjectItem or Project, or just the DTE. So, how do you use the familiar System.IServiceProvider to ask for services?

The trick is to get the latest VS SDK, add a reference to Microsoft.VisualStudio.OLE.Interop.dll and Microsoft.VisualStudio.Shell.dll and use the following simple code:

EnvDTE.Project project; // this is what you have at hand somehow.
 
IServiceProvider serviceProvider = new ServiceProvider(project.DTE as
    Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
 
DynamicTypeService typeService = (DynamicTypeService)
    serviceProvider.GetService(typeof(DynamicTypeService));

The ServiceProvider class in the Shell assembly provides the adapter you need to ask the DTE for services.

How to convert from EnvDTE.Project to IVsHierarchy and IVsProject and viceversa

I've long been looking for an answer to how to go from an automation (DTE) project to its corresponding VSIP project instance. I've been given consistently the same non-satisfactory answer: there's no way because they are two fundamentally different object models that VSIP projects may or may not expose, and there's no consistent way of going from one to the other. Or that's what they said to me at the time.

As I'm not keen on accepting a "no" for an answer, I went on to investigate how to do it, and finally got to some working code that does it. It involves the DTE, VSIP and MSBuild. What follows is the code to achieve it...

More Posts