我有一个Web API控制器,比如EmployeeController
,我们使用Autofac进行注册。现在我们创建另一个具有相同名称和路由但具有不同功能的控制器。当我们尝试使用 Autofac 注册这个新的EmployeeController
(即插件)时,我们会得到一个例外
找到了与名为
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();
答案 0 :(得分:0)
为了实现你想要的东西,我会使用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
答案 1 :(得分:0)
使用以下代码段,您可以覆盖插件控制器的相同名称。
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;
}
}