First off though, what is a Shared Resource Provider and why would you want to retrieve it?
The shared resource provider (Microsoft.Office.Server.Administration.SharedResourceProvider) is the internal class within Microsoft.Office.Server.dll which instantiates the Shared Service Provider.
I need the SharedResourceProvider instance so that I can associate configuration data for a new shared service I am developing (Widgets Service). Storing and retrieving objects in association with a SharedResourceProvider is made easier thanks to SPPersistedObject and SPPersistedChildCollection (I'll cover that in another blog post).
You can see the SharedResourceProvider in the SharePoint_Config database with the following SQL.
select
o.Name, o.Properties
from
objects o
inner
join
Classes c
on
o.ClassId=c.id
where fullname =
'Microsoft.Office.Server.Administration.SharedResourceProvider, Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'
The results will show your SharedResourceProvider instances. The Properties column is not just the properties bag. It is all of the private and public fields of the object serialized as XML. You can cut/paste the properties into an XML document and then view in Internet Explorer to see the details (below).
Notice how the configuration details for My Sites are stored within the SharedResourceProvider. Also included is the Shared Service Database. Each Shared Service associates configuration data with the Shared Resource Provider in different ways. For example, My Site configuration is stored in the SharedResourceProvider object, but BDC configuration data is stored within the database specified by m_SharedServiceDatabase. Project Server 2007 associates configuration data with a SharedResourceProvider by setting the Parent property of their configuration entities (Project Sites) to the Shared Resource Provider.
As for retrieving the Shared Resource Provider, I have seen some solutions suggested which are based on the snip below (retrieved using .net reflector against the ServerFarm class in the Microsoft.Office.Server assembly).
Fire up .net reflector and you'll see that this piece of code is not exactly straightforward. Obviously the code is accessing the "Microsoft.Office.Server.SharedResourceProvider" property of a WebApplication, but there are conditions covered for if this property is null and also another condition around the IsParentSharedResourceProvider property. To avoid fully understanding or fully copying code out of reflector, I would rather just access those internal objects and call the public methods in similar fashion as other code within MOSS assemblies.
My approach is to first obtain one of those internal objects which can lead me to the SharedResourceProvider which is associated with a Web Application. The ServerFarm will suffice. Once I have a ServerFarm, I can access public methods from there to determine the SharedResourceProvider which is associated with a given web application.
static
SPPersistedObject GetSharedResourceProvider(ServerContext context, SPSite site)
{
//our first step is to get a ServerFarm object, to do this, we must first obtain the ServerFarm type
Type serverType =Assembly.GetAssembly(context.GetType()).GetType("Microsoft.Office.Server.Administration.ServerFarm");
//now that we have a ServerFarm type, we can obtain an instance from the database
object serverFarm = site.WebApplication.Farm.GetObject(string.Empty, site.WebApplication.Farm.Id, serverType);
//the ServerFarm will give us a collection of SharedResourceProviders, we must reflect upon it to retrieve the property
PropertyInfo sharedResourceProvidersProperty = serverFarm.GetType().GetProperty("SharedResourceProviders");
IEnumerable sharedResourceProviders = (IEnumerable)sharedResourceProvidersProperty.GetValue(serverFarm, null);
//now that we have a SharedResourceProvider, we can ask it for its associated WebApplications
Type sharedResourceProviderType=Assembly.GetAssembly
(context.GetType()).GetType("Microsoft.Office.Server.Administration.SharedResourceProvider");
PropertyInfo webApplicationsProperty = sharedResourceProviderType.GetProperty("WebApplications");
//now the easy part, iterate through each SharedResourceProvider and check to see if our web application
//is in its list of WebApplications
foreach (SPPersistedObject sharedResourceProvider in sharedResourceProviders)
{
IEnumerable webApplications = (IEnumerable)webApplicationsProperty.GetValue(sharedResourceProvider, null);
foreach (SPWebApplication webApp in webApplications)
{
if (webApp.Id == site.WebApplication.Id)
{
return sharedResourceProvider;
}
}
}
return
null;
}