Wound up going with an approach that appears to be working great today, though I still have some digging to do before I find out the ramifications of this approach...
The following blog post helped immensely:
http://ikickandibite.blogspot.com/2010/04/appdomains-and-true-isolation.html
I simply enabled the legacy unhandled exception policy in the app.config:
(which, as an FYI, is still available even in .Net 4.5, which I was concerned about)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<legacyUnhandledExceptionPolicy enabled="true"/>
</runtime>
</configuration>
...From which point I can use the AppDomain.UnhandledException event to intercept an unhandled exception and unload the sub-domain...(note that I say 'intercept' here loosely...I'm still not 'catching' the exception, just taking note of it an unloading the addin in the process)
Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(IApplicationAddIn), pipelineStoreLocation, addInPath);
foreach (AddInToken token in tokens)
{
AppDomain domain = AppDomain.CreateDomain(token.Name);
domain.UnhandledException += (sender, args) =>
{
AppDomain _domain = (AppDomain) sender;
AppDomain.Unload(_domain);
};
Console.WriteLine("Initializing add-in '{0}'", token.Name);
IAddIn addin = token.Activate<IAddIn>(domain);
try
{
addin.Initialize(this);
}
catch (Exception ex)
{
Console.WriteLine("Problem initializing add-in '{0}': {1}", token.Name, ex.Message);
}
}