Simulate the model binding mechanism of ASP.net MVC by example: Set + Dictionary

Source: Internet
Author: User

In the previous two articles in this series (Simple Type + complex Type, array) we modeled the Defaultmodelbinder on simple types, complex types, and array objects by using the instance program we created to simulate the ASP.net MVC default model binding. Now we analyze how the model bindings based on collections and dictionaries are implemented in the same way. [Source code download from here]

One, set

The collection here refers to all the types of implementation ienumerable<t> interfaces that are outside the divisor group and the dictionary. Like an array-based model binding, Valueprovider can use multiple data items of the same name as elements of a collection, and the data item naming method based on the index (base zero Integer and string) also applies. We made the following refinement of the custom Defaultmodelbinder to support the model binding of the collection type.

1:public class Defaultmodelbinder
2: {
3://other Members
4:public Object Bindmodel (Type parametertype, string prefix)
5: {
6:if (!this. Valueprovider.containsprefix (prefix))
7: {
8:return null;
9:}
10:modelmetadata Modelmetadata = ModelMetadataProviders.Current.GetMetadataForType (() => null, parametertype);
11:if (!modelmetadata.iscomplextype)
12: {
13:return this. Valueprovider.getvalue (prefix). ConvertTo (ParameterType);
14:}
15:if (Parametertype.isarray)
16: {
17:return Bindarraymodel (parametertype, prefix);
18:}
19:object model = Createmodel (parametertype);
20:type Enumerabletype = Extractgenericinterface (ParameterType, typeof (Ienumerable<>));
21:if (null!= enumerabletype)
22: {
23:return Bindcollectionmodel (prefix, model, enumerabletype);
24:}
25:foreach (PropertyDescriptor property in Typedescriptor.getproperties (ParameterType))
26: {
27:string key = prefix = = ""? Property. Name:prefix + "." + property. Name;
28:property. SetValue (model, Bindmodel (property). PropertyType, key));
29:}
30:return model;
31:}
32:
33:private Object Bindcollectionmodel (string prefix, object model, Type Enumerabletype)
34: {
35:list<object> List = new list<object> ();
36:bool Numericindex;
37:ienumerable<string> indexes = getindexes (prefix, out numericindex);
38:type ElementType = enumerabletype.getgenericarguments () [0];
39:
40:if (!string. IsNullOrEmpty (prefix) && this. Valueprovider.containsprefix (prefix))
41: {
42:ienumerable enumerable = this. Valueprovider.getvalue (prefix). ConvertTo (Enumerabletype) as IEnumerable;
43:if (null!= enumerable)
44: {
45:foreach (var value in enumerable)
46: {
47:list. ADD (value);
48:}
49:}
50:}
51:foreach (var index in indexes)
52: {
53:string indexprefix = prefix + "[" + Index + "]";
54:if (!this. Valueprovider.containsprefix (Indexprefix) && Numericindex)
55: {
56:break;
57:}
58:list. ADD (Bindmodel (ElementType, Indexprefix));
59:}
60:if (list. Count = 0)
61: {
62:return null;
63:}
64:replacehelper.replacecollection (ElementType, model, list);
65:return model;
66:}
67:
68:private type Extractgenericinterface (type QueryType, type InterfaceType)
69: {
70:func<type, bool> predicate = t => t.isgenerictype && (t.getgenerictypedefinition () = = Interfa Cetype);
71:if (!predicate (QueryType))
72: {
73:return querytype.getinterfaces (). firstordefault<type> (predicate);
74:}
75:return QueryType;
76:}
77:}

As shown in the code snippet above, in the Bindmodel method we call Extractgenericinterface to determine whether the target type implements the Ienumerable<t> interface and extracts the generic element type if the interface is implemented. Implementation of model binding for a set in method Bindcollectionmodel, we get all the element objects of the target collection object in the way the array is bound, and add it to a List<object> object. The Replacehelper static method is then called replacecollection copies the elements from the list to the previously created model object. The static method Replacecollection defined in Replacehelper is defined as follows:

1:internal Static Class Replacehelper
2: {
3:private static MethodInfo Replacecollectionmethod = typeof (Replacehelper). GetMethod ("Replacecollectionimpl", BindingFlags.Static | BindingFlags.NonPublic);
4:
5:public static void Replacecollection (Type collectiontype, Object collection, Object newcontents)
6: {
7:replacecollectionmethod.makegenericmethod (new type[] {collectiontype}). Invoke (NULL, new object[] {collection, newcontents});
8:}
9:private static void Replacecollectionimpl<t> (Icollection<t> collection, IEnumerable newcontents)
10: {
11:collection. Clear ();
12:if (newcontents!= null)
13: {
14:foreach (Object Obj2 in Newcontents)
15: {
16:T item = (Obj2 is T)? ((t) obj2): Default (t);
17:collection. ADD (item);
18:}
19:}
20:}
21:}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.