Category Archives: 6471

First Experience with Pipeline Builder

Wow!


System.AddIn the easy way


Build and interface, press a button, build an add in, build a host.


Wow!


So, the pipeline builder tool really works.


You have to do a couple of things not mentioned in the documentation I used. Actually the documentation needs a little work, but its there and not too bad.


Follow the directions for the VS tool


Also


Copy the Blank project to a place to work


Rename the project as desired, or test first then rename later (I am mortified by the idea of millions of “Blank Pipeline Project” assemblies floating aorund)


Add an interface to the Contracts file. It must have the AddInContract attribute and inherit from IContract. If you want to borrow mine:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.AddIn.Contract;using PipelineHints;using System.AddIn.Pipeline;  namespace KadGen.FirstPipelineBuilderTest.Contracts{   [AddInContract()]   public interface GenerateFiles : IContract   {      string GenerateForObject(string objectName,  ref string fileName);      string GenerateForStoredProc(string objectName, ref string fileName);      string GenerateForDataTable(string objectName, ref string fileName);   }} 

If you leave off the IContract you’ll get projects but no generated cs files. Ask me how I know!


The only downside is that a lot of you will never experience the pain of creating them by hand and will be therefore so jaded that you don’t realize that the release of this tool is cause for world-wide celebrations!


I’ll blog about using this with VB after I’ve tested that more.


 


 

Pipeline Builder is Released

Yippee! I love it when someone else does my work for me.Part way through building a code generator for the otherwise nightmarish task of creating add-ins for use with System.Addin, a little bird told me that the CLR team was slaying the same dragon. Not one to stand in the way of their being heroes, and aware that they could do things in a far better way because of their knowledge, I shelved that project for a week or so.So, the pipeline builder tool is up. If you don’t know what I’m talking about, you might want to check this blog entry. It will take a while longer to catch on, but many of you have System.Addin lurking in your very near future. Pipeline Builder makes that practical.

 

Why You Care About System.AddIn

When I was fighting with AppDomains to support XML Linq code generation in my new Workflow based code generator, Bill McCarthy said “Hey did you look at System.AddIn” and I said “No, silly I’m not writing add-ins.”


Well, a few months later, I’m still trying to make it work, and have come to think it’s worth the trouble. So, first, what System.AddIn namespace offers, then why it’s so painful, then what I’m doing to fix your pain.


Simply put, System.AddIn provides abstracted/isolated app domain access. AppDomains are the boundary at which some security stuff happens, and the unit which must be unloaded as a group. You can load individual assemblies into an app domain, but to unload them, you need to unload the entire app domain.


There are a few scenarios where this is important – sandboxing code you’re running as a plug-in to your application being the one the designers had in mind. I want to use it so I can load my code generator and have it recognize changes in .NET assemblies that are generating code. With my first tool, I never solved this problem because I didn’t think brute force code generation prior to XML literals in Visual Basic made very much sense. You had a lot of the problems with XSLT (whitespace) and a nearly complete inability to search your templates (since we cannot search separately in quoted text. XML literal code generation is the best way yet to generate code – as powerful as XSLT and as easy as CodeSmith. Anyway, I can get carried away on that – it’s why I was willing to invest heavily in System.AddIn.


Along the way, I gained great respect for the complex model that supplies isolation/abstraction. If you’ve ever played  with plug-ins you know that the first version of your app and its plug-ins is OK, but keeping things in sync while multiple synergistic applications evolve is nearly impossible. The isolation model means the host only speaks to an adapter, and the add-in only needs to speak to an adapter. The adapter’s functionality and the contract can change in whatever manner is needed. This model, combined with the app domain management may lead System.AddIn to have an important role in your application if your application needs to provide variants for individual clients.


Hopefully you have a good idea what sorts of things clients are going to want to customize, and you place this into an API you hit via the add-in model. If you got it 75% correct out of the chute, it would be a miracle, so the capacity for change built into the isolation model is what actually makes this work


Literally, you load code on the fly, with whatever security limitations you want, with the ability to unload at your convenience, and pick the correct code from what’s available in a specific directory location. Cool huh!


In WinForms, the WinForms threading model prohibits UI’s in the add-in. I understand this is fixed in WPF, although I haven’t yet written a WPF add-in user interface.


So, now that you have some idea why System.AddIn is worth the trouble, why is it so painful. How could I have possibly spent so long getting it running in a sample (I just output a single quoted string right now). To provide the isolation there is a minimum of seven projects/assemblies involved. These must be deployed in a very specific directory structure for the AddIn system to find the pieces it needs when it needs it. Then there is the error reporting problem – I’ve blogged about a particularly nasty “The target application domain has been unloaded” error.  So, once you hold your mouth just right, and all your code is perfect, it’s cool. But how many of you right perfect code? And what’s this about an easy maintenance model if you have to change SEVEN assemblies to alter the API.


I’m working on an article and tool for my column in Visual Studio Magazine that will take either metadata for the API, or the interface and build the simple pass through model. This gets you started. Later when you have interface changes, the isolation model pays for itself, but at that point you understand what’s happening.


It’s going to be a pretty cool example of the “overwrite until edited” mode that my tool supports. Before I’ve used this for editable files that were pretty much empty. Now, I want to separate changes due to metadata changes – that could be significant – from those for actual mapping you did in the adapters. With luck partial methods will lead to a pretty robust set of code you can alter as you need, while still generating the main API stream.


I find it very cool to see so many fragments coming together.


 

System.Addin “The target application domain has been unloaded”

I have just escaped an Alice in Wonderland type maze with System.AddIn namespace. It’s a bit of a nightmare to create the plumbing for an add-in so stay tuned in Visual Studio Magazine for a column on how to generate this so you only do the logical work


a)      Define the add-in API


b)      Write the add-in


If you have created one of these in .NET 3.5 you know how tremendously painful it can be. The particular gotcha that I spent numerous days spread over the last three months is that the host adapter much set the contract handle:

    Private _handle As System.AddIn.Pipeline.ContractHandle    Public Sub New(ByVal contract As ILinqGenerator)      Me.contract = contract      _handle = New System.AddIn.Pipeline.ContractHandle(contract)   End Sub 

Now, you might be like me and look at that line of code and say “Hey, no one anywhere is using the _handle variable, so why not just drop it.” That would be consistent with the fact the same sample has numerous Friend methods that are never used. Heck, FxCop is even going to tell me to get rid of this line of code.


However, it’s required. Without this line of code, you get the error “The target application domain has been unloaded.”


But I said I spent days on this, over months which meant I kept coming back its fair to ask why? But that’s the subject for another post.