Ok, I needed to prove to myself that my theory of being able to just use the built in PartialCachingControl would work if it's constructor were just public. So, I resorted to a little hackery and fell back on our friend System.Reflection to instantiate an instance of the class. Here's what I ended up with:
// 23.5-hour cache lifetime, shared across all pages
PartialCachingAttribute cacheAttribute = new PartialCachingAttribute(84600, null, null, null, true);
PartialCachingControl cacher = (PartialCachingControl)Activator.CreateInstance(
typeof(PartialCachingControl), BindingFlags.NonPublic|BindingFlags.Public
|BindingFlags.ExactBinding|BindingFlags.Instance, null, new object[] { typeof(StandardFooterCachedInnerControl), cacheAttribute, this.ID }, CultureInfo.InvariantCulture);
this.Controls.Add(cacher);
So, this logic is in the constructor of my “outer” control which is responsible for always being in the code tree and overrides Control::OnPreRender to emit the stylesheet link in the <head> of the page it is contained on. Then, as the code demonstrates, in that “outer” controls constructor I construct an instance of the PartialCachingControl using the PartialCachingAttribute data to specify the cache rules it should follow (in my case, I just need to cache the data for 23.5 hours and want it shared across all web pages) and specify the type of my inner control (i.e. StandardFooterCachedInnerControl) that actually does the rendering when the data is not cached.
As expected, this works flawlessly. This is a good enough solution for me since I always control the servers on which my control will be installed. However, it is not guaranteed to work for anyone writing third party server controls, since they might be installed with lesser code access preventing them from being able to use reflection. I can only hope that the ASP.NET team will respond to my bug report and properly expose these currently hidden little features in Whidbey for those of us who are writing more complex controls.