微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET Core 3 - 覆盖自定义的默认 ControllerFactory,在其他情况下如何保存它调用?

如何解决ASP.NET Core 3 - 覆盖自定义的默认 ControllerFactory,在其他情况下如何保存它调用?

如果 DefaultControllerFactory 已成为 ASP.NET Core 3 中的内部类,如何使用自定义案例的自定义工厂覆盖认实现 IControllerFactory 并在正常情况下继续调用 DefaultControllerFactory?

services.AddSingleton<IControllerFactory,MyCustomControllerFactory>();
// this class for .NET core 2
public class MyCustomControllerFactory : DefaultControllerFactory
{
    public override object CreateController(ControllerContext context)
    {
        //custom handling...

        //base handling
        return base.CreateController(context);
    }

    public override void ReleaseController(ControllerContext context,object controller)
    {
        base.ReleaseController(context,controller);
    }
}

.NET 5 中的 DefaultControllerFactory 类是内部类,我无法调用其 CreateController 方法来尝试在 ASP MVC Core 5 环境中注册常规控制器。

//this class for .NET core 3 or .NET 5 
    public class MyCustomControllerFactory : IControllerFactory
    {
        public object CreateController(ControllerContext context)
        {
            if(/*is custom case*/) 
            { 
                /*custom actions*/ 
                return /*custom IController*/ 
            }
            return /*in this place I want calling base.CreateController(context)*/;
        }

        public void ReleaseController(ControllerContext context,object controller)
        {
            var disposable = controller as Idisposable;
            if (disposable != null) { disposable.dispose(); }
        }
    }

解决方法

我们可以重载 IControllerActivator 或 IControllerFactory。将始终调用此方法,从而创建控制器。

public class Startup
{
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddSingleton<IControllerActivator,CustomControllerActivator>();
            services.AddMvc(options => { });
        }
}

我们仍然可以调用主要的平台函数来创建控制器。我们只需要获取 IControllerActivator 或 IControllerFactory 的所有已注册实例的列表,并将我们的实现从该列表中一一排除,尝试使用此列表中的每一个创建一个控制器。重要的是要理解这个实现尽可能地简化,如果重新添加到 DI 中可以循环。

    public class CustomControllerActivator : IControllerActivator
    {
        private static object CreateController(IEnumerable<IControllerActivator> activators,ControllerContext context)
        {
            if (activators is null)
            {
                throw new ArgumentNullException(nameof(activators));
            }

            foreach (IControllerActivator activator in activators)
            {
                object controller = activator.Create(context);

                if (controller != default)
                    return controller;
            }

            return default;
        }

        private readonly IServiceProvider _provider;

        private IEnumerable<IControllerActivator> _otherActivators;

        private IEnumerable<IControllerActivator> OtherActivators
        {
            get
            {
                if (_otherActivators == null)
                    _otherActivators = _provider.GetServices<IControllerActivator>()?
                        .Where(o => !object.ReferenceEquals(this,o));

                return _otherActivators;
            }
        }
        
        public CustomControllerActivator(IServiceProvider provider)
        {
            _provider = provider ?? throw new ArgumentNullException(nameof(provider));
        }
        
        public object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException(nameof(controllerContext.ActionDescriptor));
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo == null)
            {
                throw new ArgumentException(nameof(controllerContext.ActionDescriptor.ControllerTypeInfo));
            }

            if (!IsNeedThisCustomController(controllerContext))
                return CreateController(OtherActivators,controllerContext);

            return CreateCustomController(controllerContext);
        }

        /// <summary>
        /// Do need to create this custom controller
        /// </summary>
        /// <param name="controllerContext"></param>
        /// <returns></returns>
        private bool IsNeedThisCustomController(ControllerContext controllerContext)
        {
            return false;
        }

        /// <summary>
        /// Сreating a custom controller
        /// </summary>
        /// <param name="controllerContext"></param>
        /// <returns></returns>
        private object CreateCustomController(ControllerContext controllerContext)
        {
            return default;
        }
        
        public void Release(ControllerContext context,object controller)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (controller == null)
            {
                throw new ArgumentNullException(nameof(controller));
            }

            if (controller is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。