设想:
我需要为同一个 Web 应用程序(appdomain)中的相同接口定义提供不同的接口实现,但要提供不同的“范围”。
想象一个像这样的简单分层 Web 内容结构(如果您不熟悉 SharePoint):
RootWeb (SPSite) (ctx here)
|______SubWeb1 (SPWeb) (ctx here)
|______SubWeb2 (SPWeb)
|______SubWeb3 (SPWeb)
|_______SubWeb3.1 (SPWeb) (ctx here)
|_______SubWeb3.2 (SPWeb)
RootWeb、SubWeb1 和 SubWeb3.1 提供上下文。那就是我实现了一个特定于某个层次结构级别的 AppIsolatedContext 类。如果一个级别不提供上下文,它会从父节点继承上下文,依此类推。例如,SubWeb3 将从 RootWeb 继承其上下文。然而,SubWeb3.1 提供了自己的隔离上下文。
孤立的上下文只是一个静态的 ConcurrentDictionary。
好的,到目前为止一切都很好。现在关于 Autofac(我是 Autofac 和任何其他 DI 容器的新手——虽然不是 IoC 的原则)......我不确定我如何正确设置它以正确处理对象。实际上,这应该不是什么大问题,因为对象(一旦创建)应该一直存在,直到 appdomain 被回收(将它们视为“每个独立的上下文单例”)。
我倾向于做这样的事情:
// For completeness.. a dummy page which creates a "dummy" context
public partial class _Default : Page
{
private static AppIsolatedContext _dummyContainer = new AppIsolatedContext();
public _Default()
{
_dummyContainer.ExceptionHandler.Execute("Test Message");
}
}
// The isolated context which holds all the "context" specific objects
public class AppIsolatedContext
{
public static IContainer Container { get; set; }
public IExceptionHandler ExceptionHandler { get; set; }
//public ISomething Something { get; set; }
//public ISomethingElse SomethingElse { get; set; }
public AppIsolatedContext()
{
// set up autofac
// Create your builder.
ContainerBuilder builder = new ContainerBuilder();
// Usually you're only interested in exposing the type
// via its interface:
builder.RegisterType<MailNotificationHandler>().As<INotificationHandler>();
builder.RegisterType<ExceptionHandler>().As<IExceptionHandler>();
Container = builder.Build();
using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
ExceptionHandler = scope.Resolve<IExceptionHandler>();
//Something = scope.Resolve<ISomething>();
//SomethingElse = scope.Resolve<ISomethingElse>();
}
}
}
当然,我的应用程序不限于这些“上下文单例”实例。我也会有每个请求的生命周期实例。但这就是 ASP.NET 集成模块的用途吗?我希望它们也可以无缝集成到 SharePoint (2013) 中:)
所以我的问题是我提出的建议可以吗,还是我需要弄脏我的手?如果是这样,一些方向将是惊人的......
翻阅 Autofac 的文档后,我偶然发现了它的多租户功能。我相信这也可能适合我的目的..有人可以证实这一点吗?
using System;
using System.Web;
using Autofac.Extras.Multitenant;
namespace DemoNamespace
{
public class RequestParameterStrategy : ITenantIdentificationStrategy
{
public bool TryIdentifyTenant(out object tenantId)
{
tenantId = AppIsolatedContext.Current.Id; // not implemented in the dummy class above, but present in the real thing.
return !string.IsNullOrWhiteSpace(tenantId);
}
}
}
如果有什么不是水晶 - 请不要犹豫告诉我:)