1 //------------------------------------------------------------------------------
2 // <copyright file="SourceInfo.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 //------------------------------------------------------------------------------
8 namespace System.Xml.Serialization {
11 using System.Collections;
12 using System.Diagnostics;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System.Text.RegularExpressions;
17 internal class SourceInfo {
19 //((global::System.Xml.Serialization.XmlSerializerNamespaces)p[0])
20 static Regex regex = new Regex("([(][(](?<t>[^)]+)[)])?(?<a>[^[]+)[[](?<ia>.+)[]][)]?");
21 //((global::Microsoft.CFx.Test.Common.TypeLibrary.IXSType_9)o), @"IXSType_9", @"", true, true);
22 static Regex regex2 = new Regex("[(][(](?<cast>[^)]+)[)](?<arg>[^)]+)[)]");
24 static readonly Lazy<MethodInfo> iListGetItemMethod = new Lazy<MethodInfo>(
27 return typeof(IList).GetMethod(
29 CodeGenerator.InstanceBindingFlags,
31 new Type[] { typeof(Int32) },
37 public readonly string Arg;
38 public readonly MemberInfo MemberInfo;
39 public readonly Type Type;
40 public readonly CodeGenerator ILG;
42 public SourceInfo(string source, string arg, MemberInfo memberInfo, Type type, CodeGenerator ilg) {
44 this.Arg = arg ?? source;
45 this.MemberInfo = memberInfo;
50 public SourceInfo CastTo(TypeDesc td) {
51 return new SourceInfo("((" + td.CSharpName + ")" + Source + ")", Arg, MemberInfo, td.Type, ILG);
54 public void LoadAddress(Type elementType) {
55 InternalLoad(elementType, asAddress: true);
58 public void Load(Type elementType) {
59 InternalLoad(elementType);
62 private void InternalLoad(Type elementType, bool asAddress = false) {
63 Match match = regex.Match(Arg);
65 object varA = ILG.GetVariable(match.Groups["a"].Value);
66 Type varType = ILG.GetVariableType(varA);
67 object varIA = ILG.GetVariable(match.Groups["ia"].Value);
68 if (varType.IsArray) {
71 Type eType = varType.GetElementType();
72 if (CodeGenerator.IsNullableGenericType(eType)) {
74 ConvertNullableValue(eType, elementType);
77 if (eType.IsValueType) {
85 if (elementType != null)
86 ILG.ConvertValue(eType, elementType);
92 MethodInfo get_Item = varType.GetMethod(
94 CodeGenerator.InstanceBindingFlags,
96 new Type[] { typeof(Int32) },
100 if (get_Item == null && typeof(IList).IsAssignableFrom(varType))
102 get_Item = iListGetItemMethod.Value;
105 Debug.Assert(get_Item != null);
107 Type eType = get_Item.ReturnType;
108 if (CodeGenerator.IsNullableGenericType(eType)) {
109 LocalBuilder localTmp = ILG.GetTempLocal(eType);
111 ILG.Ldloca(localTmp);
112 ConvertNullableValue(eType, elementType);
114 else if ((elementType != null) && !(eType.IsAssignableFrom(elementType) || elementType.IsAssignableFrom(eType))) {
115 throw new CodeGeneratorConversionException(eType, elementType, asAddress, "IsNotAssignableFrom");
118 Convert(eType, elementType, asAddress);
122 else if (Source == "null") {
128 if (Arg.StartsWith("o.@", StringComparison.Ordinal) || MemberInfo != null) {
129 var = ILG.GetVariable(Arg.StartsWith("o.@", StringComparison.Ordinal) ? "o" : Arg);
130 varType = ILG.GetVariableType(var);
131 if (varType.IsValueType)
132 ILG.LoadAddress(var);
137 var = ILG.GetVariable(Arg);
138 varType = ILG.GetVariableType(var);
140 if (CodeGenerator.IsNullableGenericType(varType) &&
141 varType.GetGenericArguments()[0] == elementType) {
143 ILG.LoadAddress(var);
144 ConvertNullableValue(varType, elementType);
148 ILG.LoadAddress(var);
154 if (MemberInfo != null) {
155 Type memberType = (MemberInfo is FieldInfo) ?
156 ((FieldInfo)MemberInfo).FieldType : ((PropertyInfo)MemberInfo).PropertyType;
157 if (CodeGenerator.IsNullableGenericType(memberType)) {
158 ILG.LoadMemberAddress(MemberInfo);
159 ConvertNullableValue(memberType, elementType);
162 ILG.LoadMember(MemberInfo);
163 Convert(memberType, elementType, asAddress);
167 match = regex2.Match(Source);
169 Debug.Assert(match.Groups["arg"].Value == Arg);
170 Debug.Assert(match.Groups["cast"].Value == CodeIdentifier.GetCSharpName(Type));
172 ILG.ConvertAddress(varType, Type);
174 ILG.ConvertValue(varType, Type);
177 Convert(varType, elementType, asAddress);
182 private void Convert(Type sourceType, Type targetType, bool asAddress) {
183 if (targetType != null) {
185 ILG.ConvertAddress(sourceType, targetType);
187 ILG.ConvertValue(sourceType, targetType);
191 private void ConvertNullableValue(Type nullableType, Type targetType) {
192 System.Diagnostics.Debug.Assert(targetType == nullableType || targetType.IsAssignableFrom(nullableType.GetGenericArguments()[0]));
193 if (targetType != nullableType) {
194 MethodInfo Nullable_get_Value = nullableType.GetMethod(
196 CodeGenerator.InstanceBindingFlags,
198 CodeGenerator.EmptyTypeArray,
201 ILG.Call(Nullable_get_Value);
202 if (targetType != null) {
203 ILG.ConvertValue(Nullable_get_Value.ReturnType, targetType);
208 public static implicit operator string(SourceInfo source) {
209 return source.Source;
212 public static bool operator !=(SourceInfo a, SourceInfo b) {
213 if ((object)a != null)
215 return (object)b != null;
218 public static bool operator ==(SourceInfo a, SourceInfo b) {
219 if ((object)a != null)
221 return (object)b == null;
224 public override bool Equals(object obj) {
226 return Source == null;
227 SourceInfo info = obj as SourceInfo;
229 return Source == info.Source;
233 public override int GetHashCode() {
234 return (Source == null) ? 0 : Source.GetHashCode();