If you've read any of the introductory material to VSIP (see below), you've undoubtedly come across the concept of services. A package can offer a service to itself and to other packages running inside the Visual Studio shell. If you're using the VSIP Extras Helper Classes, proffering a service is a piece of <insert favorite dessert item />. Craig Skibo had a brief blog about this a few days ago, but this should provide some more detail. Here are the simple steps you need to follow:
- Create your basic C# package using the Package Wizard in VSIP Extras
- Add a new C# file to your project and define your interface
- Add another C# file to your project and implement the interface you just defined. This will be your “service” class.
- Assign a System.Runtime.InteropServices.GuidAttribute to your service class and generate a new GUID for it.
- Add a ProvideServiceAttribute to your package class. You should pass in a string containing the GUID of the service you just implemented. For example, I added this attribute to my package class:
(What this does is put some metadata into the assembly that’s generated when you build your package. If you look at the post-build step that the wizard generated in your C# project, you’ll notice that a tool called “VSIPRegPkg.exe” is called on your package assembly. When VSIPRegPkg.exe examines your assembly, it sees the ProvideService attribute and automatically puts the correct values into the registry for you in order to have your package load and offer a service in Visual Studio. Cool!)
- In your package's initialize method, you need to actually proffer the service. This means that you are telling the shell, “If someone requests this service, give this to them”. The stuff in the previous step with registration simply lets Visual Studio know which assembly it can find your service in. Actually adding it to your “service container” in code will actually allow your package to proffer this service at load-time. The Package base class that you derive from implements IServiceContainer. This means that all you need to do is cast your package to IServiceContainer, and call AddService to proffer the service to the shell. You can do this like so:
//Instantiate the service
IAaron service = new AaronService();
//Proffer the service to the shell ((IServiceContainer)this).AddService(service.GetType(), service, true);
The true in the last argument is so your service gets promoted. This means that not only can your package call this service, but other packages that know about it can call it too.
- Build your package and run VSIPRegPkg.exe on it. (Running VSIPRegPkg.exe is done automatically if you copied BasicPkg or used the wizard to create your project).
Now you should be able to call your service from any other package that you write! To load the package and access the service, simply do something like this from your package that's calling your service:
IAaron service = (IAaron)GetService(typeof(AaronService));
I can now call any of the methods in the IAaron interface that I implemented in the AaronService class. And that, my friends, is how you proffer a service in managed code. J
As a final note to this [long] entry, AllenD wrote a blog entry about a month ago that describes how you go about accessing services provided by the VS shell from within a package. I would also recommend checking that out.