当前位置: 移动技术网 > IT编程>开发语言>.net > .NET Core开发日志——Controller

.NET Core开发日志——Controller

2018年08月19日  | 移动技术网IT编程  | 我要评论

六级真题,节能燃烧器,观暖春有感

在理清的工作流程后,接下来需要考虑的,是mvc框架如何生成controller以及它的生成时机。

根据以前asp.net mvc的经验,controller应该是由一个controllerfactory构建的。查看asp.net core mvc的源码,果然是有一个defaultcontrollerfactory类,并且不出意外的,它拥有一个createcontroller方法。

public virtual object createcontroller(controllercontext context)
{
    ...

    var controller = _controlleractivator.create(context);
    foreach (var propertyactivator in _propertyactivators)
    {
        propertyactivator.activate(context, controller);
    }

    return controller;
}

但细推其使用的场合,只出现在controllerfactoryprovider的构造方法内部,且仅是用于判断所传入的controllerfactory类型是否是defaultcontrollerfactory。

public controllerfactoryprovider(
    icontrolleractivatorprovider activatorprovider,
    icontrollerfactory controllerfactory,
    ienumerable<icontrollerpropertyactivator> propertyactivators)
{
    ...

    _activatorprovider = activatorprovider;

    // compat: delegate to the icontrollerfactory if it's not the default implementation.
    if (controllerfactory.gettype() != typeof(defaultcontrollerfactory))
    {
        _factorycreatecontroller = controllerfactory.createcontroller;
        _factoryreleasecontroller = controllerfactory.releasecontroller;
    }

    _propertyactivators = propertyactivators.toarray();
}

再看controllerfactoryprovider内部的createcontrollerfactory方法。这更像是一个真正创建controller的工厂方法。

public func<controllercontext, object> createcontrollerfactory(controlleractiondescriptor descriptor)
{
    ...

    if (_factorycreatecontroller != null)
    {
        return _factorycreatecontroller;
    }

    var controlleractivator = _activatorprovider.createactivator(descriptor);
    var propertyactivators = getpropertiestoactivate(descriptor);
    object createcontroller(controllercontext controllercontext)
    {
        var controller = controlleractivator(controllercontext);
        for (var i = 0; i < propertyactivators.length; i++)
        {
            var propertyactivator = propertyactivators[i];
            propertyactivator(controllercontext, controller);
        }

        return controller;
    }

    return createcontroller;
}

创建方式分为两种,一种是使用自定义的工厂方法,另一种是通过controlleractivatorprovider的createactivator方法。

public func<controllercontext, object> createactivator(controlleractiondescriptor descriptor)
{
    ...

    var controllertype = descriptor.controllertypeinfo?.astype();
    ...

    if (_controlleractivatorcreate != null)
    {
        return _controlleractivatorcreate;
    }

    var typeactivator = activatorutilities.createfactory(controllertype, type.emptytypes);
    return controllercontext => typeactivator(controllercontext.httpcontext.requestservices, arguments: null);
}

明白了如何创建controller,下面开始调查创建controller的时机。

controllerfactoryprovider类的createcontrollerfactory方法是被controlleractioninvokercache类的getcachedresult方法调用。

public (controlleractioninvokercacheentry cacheentry, ifiltermetadata[] filters) getcachedresult(controllercontext controllercontext)
{
    var cache = currentcache;
    var actiondescriptor = controllercontext.actiondescriptor;

    ifiltermetadata[] filters;
    if (!cache.entries.trygetvalue(actiondescriptor, out var cacheentry))
    {
        var filterfactoryresult = filterfactory.getallfilters(_filterproviders, controllercontext);
        filters = filterfactoryresult.filters;

        var parameterdefaultvalues = parameterdefaultvalues
            .getparameterdefaultvalues(actiondescriptor.methodinfo);

        var objectmethodexecutor = objectmethodexecutor.create(
            actiondescriptor.methodinfo,
            actiondescriptor.controllertypeinfo,
            parameterdefaultvalues);

        var controllerfactory = _controllerfactoryprovider.createcontrollerfactory(actiondescriptor);
        var controllerreleaser = _controllerfactoryprovider.createcontrollerreleaser(actiondescriptor);
        var propertybinderfactory = controllerbinderdelegateprovider.createbinderdelegate(
            _parameterbinder,
            _modelbinderfactory,
            _modelmetadataprovider,
            actiondescriptor);

        var actionmethodexecutor = actionmethodexecutor.getexecutor(objectmethodexecutor);

        cacheentry = new controlleractioninvokercacheentry(
            filterfactoryresult.cacheablefilters, 
            controllerfactory, 
            controllerreleaser,
            propertybinderfactory,
            objectmethodexecutor,
            actionmethodexecutor);
        cacheentry = cache.entries.getoradd(actiondescriptor, cacheentry);
    }
    else
    {
        // filter instances from statically defined filter descriptors + from filter providers
        filters = filterfactory.createuncachedfilters(_filterproviders, controllercontext, cacheentry.cachedfilters);
    }

    return (cacheentry, filters);
}

其值作为controlleractioninvokercacheentry对象的一部分被方法返回。

getcachedresult方法的上层调用者是controlleractioninvokerprovider类的onprovidersexecuting方法。

public void onprovidersexecuting(actioninvokerprovidercontext context)
{
    ...

    if (context.actioncontext.actiondescriptor is controlleractiondescriptor)
    {
        var controllercontext = new controllercontext(context.actioncontext);
        // perf: these are rarely going to be changed, so let's go copy-on-write.
        controllercontext.valueproviderfactories = new copyonwritelist<ivalueproviderfactory>(_valueproviderfactories);
        controllercontext.modelstate.maxallowederrors = _maxmodelvalidationerrors;

        var cacheresult = _controlleractioninvokercache.getcachedresult(controllercontext);

        var invoker = new controlleractioninvoker(
            _logger,
            _diagnosticsource,
            controllercontext,
            cacheresult.cacheentry,
            cacheresult.filters);

        context.result = invoker;
    }
}

controlleractioninvokercacheentry对象又被作为controlleractioninvoker对象的一部分为actioninvokerprovidercontext的result属性赋值。

再往上跟踪,到了actioninvokerfactory类的createinvoker方法。

public iactioninvoker createinvoker(actioncontext actioncontext)
{
    var context = new actioninvokerprovidercontext(actioncontext);

    foreach (var provider in _actioninvokerproviders)
    {
        provider.onprovidersexecuting(context);
    }

    for (var i = _actioninvokerproviders.length - 1; i >= 0; i--)
    {
        _actioninvokerproviders[i].onprovidersexecuted(context);
    }

    return context.result;
}

而它的调用者便是mvcroutehandler或者mvcattributeroutehandler。

public task routeasync(routecontext context)
{
    ...

    context.handler = (c) =>
    {
        var routedata = c.getroutedata();

        var actioncontext = new actioncontext(context.httpcontext, routedata, actiondescriptor);
        if (_actioncontextaccessor != null)
        {
            _actioncontextaccessor.actioncontext = actioncontext;
        }

        var invoker = _actioninvokerfactory.createinvoker(actioncontext);
        if (invoker == null)
        {
            throw new invalidoperationexception(
                resources.formatactioninvokerfactory_couldnotcreateinvoker(
                    actiondescriptor.displayname));
        }

        return invoker.invokeasync();
    };

    ...
}

到了这里创建controller的工厂方法还没有被实际调用,此时controller还是不存在的。所以还需要完成执行controlleractioninvoker的invokeasync方法,或者更准确地说是其基类resourceinvoker的invokeasync方法。

public virtual async task invokeasync()
{
    try
    {
        ...

        using (_logger.actionscope(_actioncontext.actiondescriptor))
        {
            ...

            try
            {
                await invokefilterpipelineasync();
            }
            ...
        }
    }
    ...
}

从invokefilterpipelineasync方法开始,一系列的处理流程将依据不同状态逐步展开。

private async task invokefilterpipelineasync()
{
    var next = state.invokebegin;

    var scope = scope.invoker;

    var state = (object)null;

    var iscompleted = false;

    while (!iscompleted)
    {
        await next(ref next, ref scope, ref state, ref iscompleted);
    }
}

而到了state.actionbegin这一步(controlleractioninvoker类的next方法),终于能找到controller工厂方法被执行的场合。

private task next(ref state next, ref scope scope, ref object state, ref bool iscompleted)
{
    switch (next)
    {
        case state.actionbegin:
            {
                var controllercontext = _controllercontext;

                _cursor.reset();

                _instance = _cacheentry.controllerfactory(controllercontext);

                _arguments = new dictionary<string, object>(stringcomparer.ordinalignorecase);

                var task = bindargumentsasync();
                if (task.status != taskstatus.rantocompletion)
                {
                    next = state.actionnext;
                    return task;
                }

                goto case state.actionnext;
            }
        ...
        }            
    }
}            

最后以一张流程图总结上面的探寻过程。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网