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 199 200 201 202 203 204
|
namespace System.Web.Services.Protocols {
using System;
using System.Reflection;
using System.Collections;
using System.Text.RegularExpressions;
using System.Security.Permissions;
/// <include file='doc\PatternMatcher.uex' path='docs/doc[@for="PatternMatcher"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
public sealed class PatternMatcher {
MatchType matchType;
/// <include file='doc\PatternMatcher.uex' path='docs/doc[@for="PatternMatcher.PatternMatcher"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public PatternMatcher(Type type) {
matchType = MatchType.Reflect(type);
}
/// <include file='doc\PatternMatcher.uex' path='docs/doc[@for="PatternMatcher.Match"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public object Match(string text) {
return matchType.Match(text);
}
}
internal class MatchType {
Type type;
MatchMember[] fields;
internal Type Type {
get { return type; }
}
internal static MatchType Reflect(Type type) {
MatchType matchType = new MatchType();
matchType.type = type;
MemberInfo[] memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
ArrayList list = new ArrayList();
for (int i = 0; i < memberInfos.Length; i++) {
MatchMember member = MatchMember.Reflect(memberInfos[i]);
if (member != null) list.Add(member);
}
matchType.fields = (MatchMember[])list.ToArray(typeof(MatchMember));
return matchType;
}
internal object Match(string text) {
object target = Activator.CreateInstance(type);
for (int i = 0; i < fields.Length; i++)
fields[i].Match(target, text);
return target;
}
}
internal class MatchMember {
MemberInfo memberInfo;
Regex regex;
int group;
int capture;
int maxRepeats;
MatchType matchType;
internal void Match(object target, string text) {
if (memberInfo is FieldInfo)
((FieldInfo)memberInfo).SetValue(target, matchType == null ? MatchString(text) : MatchClass(text));
else if (memberInfo is PropertyInfo) {
((PropertyInfo)memberInfo).SetValue(target, matchType == null ? MatchString(text) : MatchClass(text), new object[0]);
}
}
object MatchString(string text) {
Match m = regex.Match(text);
Type fieldType = memberInfo is FieldInfo ? ((FieldInfo)memberInfo).FieldType : ((PropertyInfo)memberInfo).PropertyType;
if (fieldType.IsArray) {
ArrayList matches = new ArrayList();
int matchCount = 0;
while (m.Success && matchCount < maxRepeats) {
if (m.Groups.Count <= group)
throw BadGroupIndexException(group, memberInfo.Name, m.Groups.Count - 1);
Group g = m.Groups[group];
foreach (Capture c in g.Captures) {
matches.Add(text.Substring(c.Index, c.Length));
}
m = m.NextMatch();
matchCount++;
}
return matches.ToArray(typeof(string));
}
else {
if (m.Success) {
if (m.Groups.Count <= group)
throw BadGroupIndexException(group, memberInfo.Name, m.Groups.Count - 1);
Group g = m.Groups[group];
if (g.Captures.Count > 0) {
if (g.Captures.Count <= capture)
throw BadCaptureIndexException(capture, memberInfo.Name, g.Captures.Count - 1);
Capture c = g.Captures[capture];
return text.Substring(c.Index, c.Length);
}
}
return null;
}
}
object MatchClass(string text) {
Match m = regex.Match(text);
Type fieldType = memberInfo is FieldInfo ? ((FieldInfo)memberInfo).FieldType : ((PropertyInfo)memberInfo).PropertyType;
if (fieldType.IsArray) {
ArrayList matches = new ArrayList();
int matchCount = 0;
while (m.Success && matchCount < maxRepeats) {
if (m.Groups.Count <= group)
throw BadGroupIndexException(group, memberInfo.Name, m.Groups.Count - 1);
Group g = m.Groups[group];
foreach (Capture c in g.Captures) {
matches.Add(matchType.Match(text.Substring(c.Index, c.Length)));
}
m = m.NextMatch();
matchCount++;
}
return matches.ToArray(matchType.Type);
}
else {
if (m.Success) {
if (m.Groups.Count <= group)
throw BadGroupIndexException(group, memberInfo.Name, m.Groups.Count - 1);
Group g = m.Groups[group];
if (g.Captures.Count > 0) {
if (g.Captures.Count <= capture)
throw BadCaptureIndexException(capture, memberInfo.Name, g.Captures.Count - 1);
Capture c = g.Captures[capture];
return matchType.Match(text.Substring(c.Index, c.Length));
}
}
return null;
}
}
static Exception BadCaptureIndexException(int index, string matchName, int highestIndex) {
return new Exception(Res.GetString(Res.WebTextMatchBadCaptureIndex, index, matchName, highestIndex));
}
static Exception BadGroupIndexException(int index, string matchName, int highestIndex) {
return new Exception(Res.GetString(Res.WebTextMatchBadGroupIndex, index, matchName, highestIndex));
}
internal static MatchMember Reflect(MemberInfo memberInfo) {
Type memberType = null;
if (memberInfo is PropertyInfo) {
PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
if (!propertyInfo.CanRead)
return null;
//
if (!propertyInfo.CanWrite)
return null;
MethodInfo getMethod = propertyInfo.GetGetMethod();
if (getMethod.IsStatic)
return null;
ParameterInfo[] parameters = getMethod.GetParameters();
if (parameters.Length > 0)
return null;
memberType = propertyInfo.PropertyType;
}
if (memberInfo is FieldInfo) {
FieldInfo fieldInfo = (FieldInfo)memberInfo;
if (!fieldInfo.IsPublic)
return null;
if (fieldInfo.IsStatic)
return null;
if (fieldInfo.IsSpecialName)
return null;
memberType = fieldInfo.FieldType;
}
object[] attrs = memberInfo.GetCustomAttributes(typeof(MatchAttribute), false);
if (attrs.Length == 0) return null;
MatchAttribute attr = (MatchAttribute)attrs[0];
MatchMember member = new MatchMember();
member.regex = new Regex(attr.Pattern, RegexOptions.Singleline | (attr.IgnoreCase ? RegexOptions.IgnoreCase | RegexOptions.CultureInvariant : 0));
member.group = attr.Group;
member.capture = attr.Capture;
member.maxRepeats = attr.MaxRepeats;
member.memberInfo = memberInfo;
if (member.maxRepeats < 0) // unspecified
member.maxRepeats = memberType.IsArray ? int.MaxValue : 1;
if (memberType.IsArray) {
memberType = memberType.GetElementType();
}
if (memberType != typeof(string)) {
member.matchType = MatchType.Reflect(memberType);
}
return member;
}
}
}
|