ASP.NET MVC Model绑定(三)

ASP.NET MVC Model绑定(三)

前言

看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给咱们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Model绑定器提供程序的实现以及解决一下上篇遗留的问题。编程

第一个问题是ModelBinderProviderCollection类型的执行过程?框架

还有个本篇的问题就是一样的向系统上下文中注册Model绑定器和Model绑定器提供程序,哪个优先级更高?ide

 

Model绑定

  • IModelBinder、自定义Model绑定器简单实现
  • Model绑定器在MVC框架中的位置
  • MVC中的默认Model绑定器生成过程
  • IModelBinderProvider的简单应用
  • IValueProvider在MVC框架中生成的位置以及过程
  • IValueProvider的应用场景
  • IValueProvider的实现之NameValueCollectionValueProvider

 

IModelBinderProvider的简单应用

首先咱们先看一下IModelBinderProvider类型的定义,代码1-1:。测试

代码1-1spa

    public interface IModelBinderProvider
    {
        // 摘要:
        //     返回指定类型的模型联编程序。
        //
        // 参数:
        //   modelType:
        //     模型的类型。
        //
        // 返回结果:
        //     指定类型的模型联编程序。
        IModelBinder GetBinder(Type modelType);
    }

在代码1-1中咱们看出,其中的GetBinder()方法是根据ViewModel的类型来作一些操做,最后返回Model绑定器。如今咱们自定义实现一个Model绑定器提供程序代码1-2。code

代码1-2对象

using System.Web.Mvc;
using ConsoleApplication2;

namespace MvcApplication.Infrastructure
{
    public class MyCustomModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(Type modelType)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }
            if (modelType == typeof(Customer))
            {
               //返回对应Customer类型的Model绑定器
            }
            return null;
        }
    }
}

在代码1-2中咱们根据modelType判断是不是Customer类型,而后返回对应Customer类型的Model绑定器。为何这里的实现是空的,由于我想把咱们前面讲解过的IoC框架用起来,让Model绑定器提供程序跟Model绑定器解除耦合,想把IoC框架的应用定义在当前系统的上下文中,咱们看一下代码实现,代码1-3。blog

代码1-3ip

using System.Web.Mvc;
using Ninject;
using System.ComponentModel;
using System.ComponentModel.Design;
using MvcApplication.Infrastructure.NinjectControllerPart;


namespace MvcApplication
{
    public class MVCSystemContext
    {
        private static MVCSystemContext _MVCSystemContext;

        public static MVCSystemContext Context
        {
            get
            {
                if (_MVCSystemContext == null)
                {
                    _MVCSystemContext = new MVCSystemContext();
                }
                return _MVCSystemContext;
            }
        }

        private ServiceContainer _serviceContainer;

        private MVCSystemContext()
        {
            _serviceContainer = new ServiceContainer();
            _serviceContainer.AddService(typeof(NinjectController),NinjectController.Instance);
        }

        public NinjectController NinjectController
        {
            get
            {
                return (NinjectController)_serviceContainer.GetService(typeof(NinjectController));
            }
        }


    }
}

代码1-3当中就是我定义的当前系统上下文了,只不过这个是给本身用的,上下文对象中想必是不会把所用到的全部数据或者是功能都添加在里面的,只是添加个引用而已,如代码1-3中的NinjectController属性,NinjectController属性对应的类型就是NinjectController类型,NinjectController类型的做用就是提供IoC框架的功能,咱们看一下代码1-4中对于NinjectController类型的定义。get

代码1-4

using Ninject;

namespace MvcApplication.Infrastructure.NinjectControllerPart
{
    public class NinjectController
    {
        private static NinjectController _Instance;

        public static NinjectController Instance
        {
            get 
            {
                return _Instance = new NinjectController();
            }
        }

        private IKernel _ninjectKernel;

        private NinjectController()
        {
            _ninjectKernel = new StandardKernel();
        }

        public void AddKernelBind<T, U>()where U:T
        {
            _ninjectKernel.Bind<T>().To<U>();
        }

        public T GetValueType<T>(Type keyType)
        {
            var valueType = _ninjectKernel.Get(keyType);
            return (T)valueType;
        }
    }
}

其中对于Ninject这个IoC框架进行了一个最基础的功能封装,有的朋友可能会问为何不公开个一个属性,何须这样画蛇添足,由于我对Ninject的使用也不是很熟练,对于这部分的封装我只是让其简单的公开了两个功能,一个是绑定一个是获取值,这样让这部份内容还在个人可控范围内,若是是公开属性的话,其余人的胡乱使用致使错误的话是不可控的。

切回主题,这样基础定义好了事后,咱们再修改1-2中的代码,把具体实现给加上,示例代码1-5所示。

代码1-5

if (modelType == typeof(Customer))
{
    //返回对应Customer类型的Model绑定器
    return MVCSystemContext.Context.NinjectController.GetValueType<IModelBinder>(typeof(IModelBinder));
}

能够看到代码1-5中,根据咱们自定义上下文中的提供的IoC功能获取到绑定在IoC框架中的值,那么绑定又是在哪里呢?跟ASP.NET MVC Model绑定(一)所演示的那样,仍是在项目的Global.asax文件中的MvcApplication类型的Application_Start()方法中添加如代码1-6。

代码1-6

MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>();
ModelBinderProviders.BinderProviders.Add(new MyCustomModelBinderProvider());

代码1-6分别作了两个操做,先是把对应Customer类型的Model绑定器注册到了咱们自定义上下文的IoC中,而后再把针对处理Customer类型的Model绑定器提供程序注册到系统中。运行结果如图1.

图1

其中涉及到全部部分的代码和ASP.NET MVC Model绑定(一)篇幅中的同样,因此这里就没有列举了。

在此咱们根据上篇中最后图2所示的那样,能够判断出ModelBinderProviderCollection类型的执行过程是根据当前ParameterDescriptor类型所提供的Model类型对比咱们注册到或者是系统默认提供的Model绑定器提供程序集合,若是有是针对ParameterDescriptor类型所提供的Model类型(上述示例中是Customer类型)则会有Model绑定器的返回,而后再根据Model绑定器进行Model绑定。

 

好了如今第一个问题解决了,来解决第二个问题。来看代码1-7所示。

代码1-7

    public class MyCustomModelBinder:IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            return new Customer()
            {
                CustomerID = "010",
                Name = "测试人员",
                RegistrationDate = DateTime.Now,
                Address = new Address()
                {
                    AddressName = "天空之城"
                }
            };
        }
    }

    public class MyCustomModelBinder_Test : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            return new Customer()
            {
                CustomerID = "010",
                Name = "测试人员",
                RegistrationDate = DateTime.Now,
                Address = new Address()
                {
                    AddressName = "这里是根据Model绑定器绑定执行的Model"
                }
            };
        }
    }

看到代码1-7中的MyCustomModelBinder_Test 类型内部Customer类型实例内部的AddressName值已经更改的和以前的不同了。再看一下注册端的修改,示例代码1-8。

代码1-8

ModelBinders.Binders.Add(typeof(Customer), new Binders.MyCustomModelBinder_Test());
MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>();
ModelBinderProviders.BinderProviders.Add(new MyCustomModelBinderProvider());

代码1-8中,咱们把新定义的MyCustomModelBinder_Test 类型注册到了系统的Model绑定器集合中,看一下到底是哪个级别更高一点。

来看运行结果图2

图2

看到图2这个结果,想必已经知道了是哪一个级别更高一点了。

 

 

 

做者:金源

出处:http://www.cnblogs.com/jin-yuan/

本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面

相关文章
相关标签/搜索