1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
//------------------------------------------------------------------------------
// <copyright file="PropertyMapper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* PropertyMapper.cs
*
* Copyright (c) 1999 Microsoft Corporation
*/
namespace System.Web.UI {
using System;
using System.Collections;
using System.Reflection;
using System.Web.Util;
using System.ComponentModel;
internal sealed class PropertyMapper {
private const char PERSIST_CHAR = '-';
private const char OM_CHAR = '.';
private const string STR_OM_CHAR = ".";
/*
* Maps persisted attribute names to the object model equivalents.
* This class should not be instantiated by itself.
*/
private PropertyMapper() {
}
/*
* Returns the PropertyInfo or FieldInfo corresponding to the
* specified property name.
*/
internal static MemberInfo GetMemberInfo(Type ctrlType, string name, out string nameForCodeGen) {
Type currentType = ctrlType;
PropertyInfo propInfo = null;
FieldInfo fieldInfo = null;
string mappedName = MapNameToPropertyName(name);
nameForCodeGen = null;
int startIndex = 0;
while (startIndex < mappedName.Length) { // parse thru dots of object model to locate PropertyInfo
string propName;
int index = mappedName.IndexOf(OM_CHAR, startIndex);
if (index < 0) {
propName = mappedName.Substring(startIndex);
startIndex = mappedName.Length;
}
else {
propName = mappedName.Substring(startIndex, index - startIndex);
startIndex = index + 1;
}
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase;
//
try {
propInfo = TargetFrameworkUtil.GetProperty(currentType, propName, flags);
}
catch (AmbiguousMatchException) {
flags |= BindingFlags.DeclaredOnly;
propInfo = TargetFrameworkUtil.GetProperty(currentType, propName, flags);
}
if (propInfo == null) { // could not find a public property, look for a public field
fieldInfo = TargetFrameworkUtil.GetField(currentType, propName, flags);
if (fieldInfo == null) {
nameForCodeGen = null;
break;
}
}
propName = null;
if (propInfo != null) { // found a public property
currentType = propInfo.PropertyType;
propName = propInfo.Name;
}
else { // found a public field
currentType = fieldInfo.FieldType;
propName = fieldInfo.Name;
}
// Throw if the type of not CLS-compliant (ASURT 83438)
if (!IsTypeCLSCompliant(currentType)) {
throw new HttpException(SR.GetString(SR.Property_Not_ClsCompliant, name, ctrlType.FullName, currentType.FullName));
}
if (propName != null) {
if (nameForCodeGen == null)
nameForCodeGen = propName;
else
nameForCodeGen += STR_OM_CHAR + propName;
}
}
if (propInfo != null)
return propInfo;
else
return fieldInfo;
}
private static bool IsTypeCLSCompliant(Type type) {
// We used to check this by looking up the CLSCompliantAttribute, but that was
// way too inefficent. So instead, we just juck for a few specific types
if ((type == typeof(SByte)) ||
(type == typeof(TypedReference)) ||
(type == typeof(UInt16)) ||
(type == typeof(UInt32)) ||
(type == typeof(UInt64)) ||
(type == typeof(UIntPtr))) {
return false;
}
return true;
}
/*
* Maps the specified persisted name to its object model equivalent.
* The convention is to map all dashes to dots.
* For example : Font-Size maps to Font.Size
* HeaderStyle-Font-Name maps to HeaderStyle.Font.Name
*/
internal static string MapNameToPropertyName(string attrName) {
return attrName.Replace(PERSIST_CHAR,OM_CHAR);
}
internal static object LocatePropertyObject(object obj, string mappedName, out string propertyName, bool inDesigner) {
object currentObject = obj;
Type currentType = obj.GetType();
propertyName = null;
int index;
int startIndex = 0;
// step through the dots of the object model to extract the PropertyInfo
// and object on which the property will be set
while (startIndex < mappedName.Length) {
index = mappedName.IndexOf(OM_CHAR, startIndex);
// If we didn't find a separator, we're on the last piece
if (index < 0)
break;
// There is a sub property, so get its info and iterate
propertyName = mappedName.Substring(startIndex, index - startIndex);
startIndex = index + 1;
currentObject = FastPropertyAccessor.GetProperty(currentObject, propertyName, inDesigner);
if (currentObject == null)
return null;
}
// Avoid a useless call to Substring if possible
if (startIndex > 0)
propertyName = mappedName.Substring(startIndex);
else
propertyName = mappedName;
return currentObject;
}
/*
* Walks the object model using the mapped property name to get the
* value of an instance's property.
*/
internal static PropertyDescriptor GetMappedPropertyDescriptor(object obj, string mappedName, out object childObject, out string propertyName, bool inDesigner)
{
childObject = LocatePropertyObject(obj, mappedName, out propertyName, inDesigner);
if (childObject == null) return null;
PropertyDescriptorCollection properties = TargetFrameworkUtil.GetProperties(childObject);
return properties[propertyName];
}
/*
* Walks the object model using the mapped property name to set the
* value of an instance's property.
*/
internal static void SetMappedPropertyValue(object obj, string mappedName, object value, bool inDesigner) {
string propertyName;
object childObj = LocatePropertyObject(obj, mappedName, out propertyName, inDesigner);
if (childObj == null) return;
FastPropertyAccessor.SetProperty(childObj, propertyName, value, inDesigner);
}
}
}
|