- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 Simple Injector 创建一个插件架构,允许我配置一个插件 “abc”(一个租户),如果我提供了 ?tenant=abc
在我请求的查询字符串中,它将覆盖 “核心” 插件并改用它的 Controller 。
例如,如果我在“核心”中有以下 Controller :
public HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "This is core.";
return View();
}
}
而且,如果我指定了 ?tenant=abc
,那么它应该加载“abc”插件 Controller :
public HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "This is abc.";
return View();
}
}
问题是,我不太确定从哪里开始。我一直在阅读以下帖子,但似乎仍然没有将所有这些部分组合在一起的“胶水”。
谁能给我一点“快速入门”,这样我就可以组装一个支持上述功能的基本“hello world”?
编辑:我想解决方案将与此类似(Autofac 的 Multi-Tenancy 实现):
// First, create your application-level defaults using a standard
// ContainerBuilder, just as you are used to.
var builder = new ContainerBuilder();
builder.RegisterType<Consumer>().As<IDependencyConsumer>().InstancePerDependency();
builder.RegisterType<BaseDependency>().As<IDependency>().SingleInstance();
var appContainer = builder.Build();
// Once you've built the application-level default container, you
// need to create a tenant identification strategy.
var tenantIdentifier = new MyTenantIdentificationStrategy();
// Now create the multitenant container using the application
// container and the tenant identification strategy.
var mtc = new MultitenantContainer(tenantIdentifier, appContainer);
// Configure the overrides for each tenant by passing in the tenant ID
// and a lambda that takes a ContainerBuilder.
mtc.ConfigureTenant('1', b => b.RegisterType<Tenant1Dependency>().As<IDependency>().InstancePerDependency());
mtc.ConfigureTenant('2', b => b.RegisterType<Tenant2Dependency>().As<IDependency>().SingleInstance());
// Now you can use the multitenant container to resolve instances.
// Resolutions will be tenant-specific.
var dependency = mtc.Resolve<IDependency>();
有没有办法用 SimpleInjector 做这种事情?
最佳答案
有很多方法可以做到这一点,这完全取决于您的具体需要。我目前正在开发的应用程序使用模块化方法,我们有一个“外壳”MVC 项目和多个“模块”MVC 项目,每个项目都有自己的 Controller / View 集,而它们有时使用共享功能(例如 View 和模板)从外壳。但这不是基于租户的方法。在这里,我们尝试隔离应用程序的各个部分,以降低复杂性。但是我们不会动态加载我们的 Controller ;外壳仅引用模块项目。每个模块项目包含一个或多个区域,我们在构建时将区域文件夹复制到 shell 的/areas 。这是一种花了很多时间才正确的方法。但我离题了。
在您的情况下,我认为最好从自定义 ControllerFactory
开始.在此工厂内,您可以根据特定条件决定加载哪个 Controller 。我们也使用这种方法,并根据区域将工厂重定向到特定的模块程序集。
这实际上不是您在 DI 容器 IMO 级别解决的问题。您可以在此处将 DI 容器从图片中移除。这是 cuch 自定义 Controller 工厂的示例:
public class CustomControllerFactory : DefaultControllerFactory {
protected override Type GetControllerType(RequestContext requestContext,
string controllerName) {
string tenant = requestContext.HttpContext.Request.QueryString["tenant"];
string[] namespaces;
if (tenant != null) {
namespaces = new[] { "MyComp.Plugins." + tenant };
} else {
namespaces = new[] { typeof(HomeController).Namespace };
}
requestContext.RouteData.DataTokens["Namespaces"] = namespaces;
var type = base.GetControllerType(requestContext, controllerName);
return type;
}
}
在这个例子中,我假设每个租户都有自己的程序集,或者至少有自己的命名空间,以“MyComp.Plugins”开头。后面是租户的名字。通过设置路由数据的“命名空间”数据 token ,我们可以构建 MVC 以在特定命名空间中进行搜索。
您可以按如下方式替换 MVC 的默认 Controller 工厂:
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
如果您的插件 Controller 位于 Web 应用程序/bin 文件夹中的程序集中的“MyComp.Plugins.abc”命名空间中,这应该可以工作。
更新
关于基于当前租户注册服务。有多种方法可以解决这个问题。首先要注意的是,Simple Injector 没有任何开箱即用的功能,但我会说没有必要。这里有两种解决方法。
两个选项使用相同的 ITenantContext
抽象。这是抽象:
public interface ITenantContext {
string TenantId { get; }
}
并且每个抽象都应该有一个实现。这是针对您(当前)需求的:
public class AspNetQueryStringTenantContext : ITenantContext {
public string TenantId {
get { return HttpContext.Current.Request.QueryString["tenant"]; }
}
}
选项 1:使用代理类。
一个很常见的事情是为给定的 IDependency
创建一个代理抽象,它将决定转发到哪个具体实现(基于当前租户)。这可能看起来像这样:
public class TenantDependencyProxy : IDependency {
private readonly Containt container;
private readonly ITenantContext context;
public TenantDependencyProxy(Container container, ITenantContext context) {
this.container = container;
this.context = context;
}
object IDependency.DependencyMethod(int x) {
return this.GetTenantDependency().DependencyMethod(x);
}
private IDependency GetTenantDependency() {
switch (this.context.TenantId) {
case "abc": return this.container.GetInstance<Tenant1Dependency>();
default: return this.container.GetInstance<Tenant2Dependency>();
}
}
}
注册看起来如下:
ITenantContext tenantContext = new AspNetQueryStringTenantContext();
container.RegisterSingle<ITenantContext>(tenantContext);
container.Register<Tenant1Dependency>(Lifestyle.Transient);
container.Register<Tenant2Dependency>(Lifestyle.Singleton);
container.Register<IDependency, TenantDependencyProxy>(Lifestyle.Singleton);
现在应用程序中的所有内容都可以简单地依赖于 IDependency
根据某些运行时条件,他们将使用 Tenant1Dependency
或 Tenant2Dependency
.
选项 2:在工厂委托(delegate)中实现该代理功能。
使用这个选项,您仍然可以实现代理的 switch-case 语句,但是您将它放在您注册的工厂委托(delegate)中:
ITenantContext tenantContext = new AspNetQueryStringTenantContext();
container.RegisterSingle<ITenantContext>(tenantContext);
container.Register<Tenant1Dependency>(Lifestyle.Transient);
container.Register<Tenant2Dependency>(Lifestyle.Singleton);
container.Register<IDependency>(() => {
switch (tenantContext.TenantId) {
case "abc": return this.container.GetInstance<Tenant1Dependency>();
default: return this.container.GetInstance<Tenant2Dependency>();
}
});
这消除了对代理类的需要。
如果您有许多需要切换的服务,则可以轻松地重构此代码,以便将此代码重用于许多抽象。如果您有许多这样的服务想要像这样切换,我建议您仔细研究一下您的架构,因为在我看来,您可能只需要其中的一些服务。
关于c# - 带有简单注入(inject)器的插件架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26822155/
我在互联网上搜索了很多小时,但没有找到满意的结果,所以 -VSTO Addin 和 COM Addin(我们作为类库项目制作并使用 Excel 对象)之间有什么区别?VSTO 项目是否有任何限制,例如
我在互联网上搜索了很多小时,但没有找到满意的结果,所以 -VSTO Addin 和 COM Addin(我们作为类库项目制作并使用 Excel 对象)之间有什么区别?VSTO 项目是否有任何限制,例如
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在寻找有关如何构建可扩展 WCF 服务器(具有动态加载的服务)的建议,最好使用 System.Addins 或 MEF。 服务器应托管实现最小“插件”API(StartService/StopSe
有没有一种方法可以使用加载浏览器扩展/插件/插件的 headless 浏览器(即 PhantomJS、Selenium)来运行自动测试? 更具体地说,我想模拟广告拦截器(如 Ghostery、ad-b
我是 gradle 的新手,我使用 artifactory 作为我的 repo 服务器。我在网上查看了如何将我的项目发布到我的 repo 服务器,发现我可以使用 maven-publish 或使用 a
我想禁用某些状态的点击/事件,并仅使少数状态可点击。我通读了http://newsignature.github.io/us-map/处的文档,并且找不到与此问题相关的任何内容。 最佳答案 http:
据我了解,在Intellij中使用idea插件打开Maven构建的项目并不是最好的方法,即调用: mvn idea:idea 但是直接打开pom文件(Intellij有默认的Maven插件);同样的事
使用Artifactory plugin对于 Jenkins pipeline 来说是一种幸福,只要遵循文档就可以了。但后来我介绍了Maven Flatten plugin解析父模块和子模块 mvn
我已经安装了Elasticsearch版本1.7.1。一切正常。我也安装了 JDBC 驱动程序。检查下面我的插件文件夹 目录E:\Xampp\htdocs\my-elastic\elasticsear
在我使用 webpack common chunks 插件创建包含第三方库(如 angular、react、lodash 等)的 vendor 包之前,但后来我知道了 webpack dll
我们正在尝试使用(Jenkins、sonar、eclipse ...)安装 CI 平台。 为了让每个开发人员都可以在提交之前对他的代码进行分析,我想知道两种选择: 使用 Sonar 插件运行本地分析。
我知道这是一个比较特殊的问题。尽管如此,也许有些人知道这一点: 我想在 Eclipse 中使用 Maven 编译 Hector=> 分支:0.7.0 和标签:hector-0.7.0-29(https
我卡住了。我一直在尝试寻找或自己创建一个简单的准系统示例,说明如何为 VS 2010 Express 创建 Outlook 插件。我知道这在 VS 2010 Pro 中更简单,但是,在快速版本中真的不
我有以下排除过滤器来忽略所有 R 文件类: findbugs-exclude-filter.xml 当我将它用于 FindBugs-IDEA 插件时,它可以
我刚开始玩 CakePHP,我发现了 Wildflower CMS .我喜欢这个想法,并打算开始修补它。不过,我有一个问题。 在自述文件中,我发现了以下内容:“Wildflower 不是也不会是 Ca
虽然现在大部分情况都是使用n-api来编写插件,但是底层毕竟是v8(和libuv),使用v8编写简单的插件,同时熟悉v8的使用。 本文介绍在写c++插件时,简单又常用的写法,其实本质上,写插件
本篇是 Python 系列教程第 3 篇,更多内容敬请访问我的 Python 合集 Visual Studio Code的安装非常简单,就不放这里增加文章篇幅了。 相比PyCharm,V
Maven – 插件 什么是 Maven 插件? Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。Maven 插件通常被用来: 创建 jar 文件 创建 war
我正在编写一个插件来添加带有标签 [deposit_page] 的页面;该标记应替换为一些 PHP 代码。 这就是我所拥有的,但它不起作用。有什么我遗漏或做错了什么吗? function deposi
我是一名优秀的程序员,十分优秀!