如何让插件webAPI覆盖现有的webAPI
我有一个Web API控制器,例如EmployeeController
,我们使用Autofac注册。现在我们创建另一个具有相同名称和路由的控制器,但具有不同的功能。当我们尝试使用Autofac注册这个新EmployeeController
(即插件),我们会得到一个异常喜欢如何让插件webAPI覆盖现有的webAPI
多种类型的发现匹配命名
EmployeeController
的控制器。
我的目标是成功注入第二个控制器,并用它覆盖第一个控制器的功能。
项目A - >核心项目
namespace Main.API
{
public class EmployeeController : ApiController
{
// Some Logic
}
}
项目B - >插件项目
以后消费者要覆盖与同一控制器名员工控制器
namespace Plugin.API
{
public class EmployeeController : ApiController
{
// Some Logic
}
}
Autofac
// assemblies contains Main.API.dll & Plugin.API.dll
builder.RegisterApiControllers(assemblies.ToArray()).InstancePerRequest();
为了实现你想我会用AOP concept这将使它更容易实现和更强大的东西。
Castle DynamicProxy项目为.net提供AOP概念,可以使用Autofac与Autofac.Extras.DynamicProxy2
nuget包。
你将有只有1 EmployeeController
在您的主项目
namespace Main.API
{
public class EmployeeController : ApiController
{
public virtual String Get(Int32 id)
{
// Some Logic
}
}
}
在你的插件项目
和各种IInterceptor
:
namespace Plugin
{
public class XEmployeeeControllerInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if(!invocation.Method.Name == nameof(Core.APi.EmployeeController.Get))
{
return;
}
invocation.Proceed();
// alter return value
invocation.ReturnValue = invocation.ReturnValue + "-intercepted";
}
}
}
然后注册这样的事情:
builder.RegisterApiControllers(assemblies.ToArray())
.InstancePerRequest()
.EnableClassInterceptors();
builder.RegisterAssemblyTypes(assemblies.ToArray())
.As<IInterceptor>();
见Type Interceptors欲了解更多信息
首先我要感谢Cyril Durand。让我知道,如果有任何可能性,只需在执行RegisterApiControllers时从Main.API dll中排除类型(EmployeeController)?。 在DI注册之前我会检查Main和Plugin之间是否存在相同类型,如果可用,我想从Main排除类型,然后自动从Plugin访问相同类型。 – user1611257
使用下面的代码片段可以覆盖同名的插件控制器。
public class CustomHttpControllerSelector : DefaultHttpControllerSelector
{
private readonly HttpConfiguration _configuration;
private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
/// <summary>
/// custom http controllerselector
/// </summary>
/// <param name="config"></param>
public CustomHttpControllerSelector(HttpConfiguration config) : base(config)
{
_configuration = config;
_controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDictionary);
}
/// <summary>
/// GetControllerMapping
/// </summary>
/// <returns></returns>
public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
return _controllers.Value;
}
private Dictionary<string, HttpControllerDescriptor> InitializeControllerDictionary()
{
var controllers = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
foreach (Type t in controllerTypes)
{
var controllerName = t.Name.Remove(t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
//Remove Core API Controller and add the Plugin API controller.
if (controllers.Keys.Contains(controllerName) && t.Namespace.Contains("Plugin"))
{
controllers.Remove(controllerName);
}
if (!controllers.Keys.Contains(controllerName))
{
controllers[controllerName] = new HttpControllerDescriptor(_configuration, t.Nam`enter code here`e, t);
}
}
return controllers;
}
}
我认为你会为此工作的自定义注册源。 http://docs.autofac.org/en/latest/advanced/registration-sources.html – Jehof