簡體   English   中英

如何允許插件webAPI覆蓋現有的webAPI

[英]How to allow a plugin webAPI to override an existing webAPI

我有一個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();

為了實現您想要的功能,我將使用AOP概念 ,這將使其更易於實現且功能更強大。

城堡DynamicProxy項目提供AOP概念.NET,可以通過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>(); 

有關更多信息,請參見類型攔截器

使用以下代碼片段,您可以覆蓋相同名稱的插件控制器。

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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM