| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- //------------------------------------------------------------------------------
- // <copyright file="SourceInfo.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">Microsoft</owner>
- //------------------------------------------------------------------------------
- namespace System.Xml.Serialization {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Text.RegularExpressions;
- internal class SourceInfo {
- //a[ia]
- //((global::System.Xml.Serialization.XmlSerializerNamespaces)p[0])
- static Regex regex = new Regex("([(][(](?<t>[^)]+)[)])?(?<a>[^[]+)[[](?<ia>.+)[]][)]?");
- //((global::Microsoft.CFx.Test.Common.TypeLibrary.IXSType_9)o), @"IXSType_9", @"", true, true);
- static Regex regex2 = new Regex("[(][(](?<cast>[^)]+)[)](?<arg>[^)]+)[)]");
- static readonly Lazy<MethodInfo> iListGetItemMethod = new Lazy<MethodInfo>(
- () =>
- {
- return typeof(IList).GetMethod(
- "get_Item",
- CodeGenerator.InstanceBindingFlags,
- null,
- new Type[] { typeof(Int32) },
- null
- );
- });
- public string Source;
- public readonly string Arg;
- public readonly MemberInfo MemberInfo;
- public readonly Type Type;
- public readonly CodeGenerator ILG;
- public SourceInfo(string source, string arg, MemberInfo memberInfo, Type type, CodeGenerator ilg) {
- this.Source = source;
- this.Arg = arg ?? source;
- this.MemberInfo = memberInfo;
- this.Type = type;
- this.ILG = ilg;
- }
- public SourceInfo CastTo(TypeDesc td) {
- return new SourceInfo("((" + td.CSharpName + ")" + Source + ")", Arg, MemberInfo, td.Type, ILG);
- }
- public void LoadAddress(Type elementType) {
- InternalLoad(elementType, asAddress: true);
- }
- public void Load(Type elementType) {
- InternalLoad(elementType);
- }
- private void InternalLoad(Type elementType, bool asAddress = false) {
- Match match = regex.Match(Arg);
- if (match.Success) {
- object varA = ILG.GetVariable(match.Groups["a"].Value);
- Type varType = ILG.GetVariableType(varA);
- object varIA = ILG.GetVariable(match.Groups["ia"].Value);
- if (varType.IsArray) {
- ILG.Load(varA);
- ILG.Load(varIA);
- Type eType = varType.GetElementType();
- if (CodeGenerator.IsNullableGenericType(eType)) {
- ILG.Ldelema(eType);
- ConvertNullableValue(eType, elementType);
- }
- else {
- if (eType.IsValueType) {
- ILG.Ldelema(eType);
- if (!asAddress) {
- ILG.Ldobj(eType);
- }
- }
- else
- ILG.Ldelem(eType);
- if (elementType != null)
- ILG.ConvertValue(eType, elementType);
- }
- }
- else {
- ILG.Load(varA);
- ILG.Load(varIA);
- MethodInfo get_Item = varType.GetMethod(
- "get_Item",
- CodeGenerator.InstanceBindingFlags,
- null,
- new Type[] { typeof(Int32) },
- null
- );
- if (get_Item == null && typeof(IList).IsAssignableFrom(varType))
- {
- get_Item = iListGetItemMethod.Value;
- }
- Debug.Assert(get_Item != null);
- ILG.Call(get_Item);
- Type eType = get_Item.ReturnType;
- if (CodeGenerator.IsNullableGenericType(eType)) {
- LocalBuilder localTmp = ILG.GetTempLocal(eType);
- ILG.Stloc(localTmp);
- ILG.Ldloca(localTmp);
- ConvertNullableValue(eType, elementType);
- }
- else if ((elementType != null) && !(eType.IsAssignableFrom(elementType) || elementType.IsAssignableFrom(eType))) {
- throw new CodeGeneratorConversionException(eType, elementType, asAddress, "IsNotAssignableFrom");
- }
- else {
- Convert(eType, elementType, asAddress);
- }
- }
- }
- else if (Source == "null") {
- ILG.Load(null);
- }
- else {
- object var;
- Type varType;
- if (Arg.StartsWith("o.@", StringComparison.Ordinal) || MemberInfo != null) {
- var = ILG.GetVariable(Arg.StartsWith("o.@", StringComparison.Ordinal) ? "o" : Arg);
- varType = ILG.GetVariableType(var);
- if (varType.IsValueType)
- ILG.LoadAddress(var);
- else
- ILG.Load(var);
- }
- else {
- var = ILG.GetVariable(Arg);
- varType = ILG.GetVariableType(var);
- if (CodeGenerator.IsNullableGenericType(varType) &&
- varType.GetGenericArguments()[0] == elementType) {
- ILG.LoadAddress(var);
- ConvertNullableValue(varType, elementType);
- }
- else {
- if (asAddress)
- ILG.LoadAddress(var);
- else
- ILG.Load(var);
- }
- }
- if (MemberInfo != null) {
- Type memberType = (MemberInfo is FieldInfo) ?
- ((FieldInfo)MemberInfo).FieldType : ((PropertyInfo)MemberInfo).PropertyType;
- if (CodeGenerator.IsNullableGenericType(memberType)) {
- ILG.LoadMemberAddress(MemberInfo);
- ConvertNullableValue(memberType, elementType);
- }
- else {
- ILG.LoadMember(MemberInfo);
- Convert(memberType, elementType, asAddress);
- }
- }
- else {
- match = regex2.Match(Source);
- if (match.Success) {
- Debug.Assert(match.Groups["arg"].Value == Arg);
- Debug.Assert(match.Groups["cast"].Value == CodeIdentifier.GetCSharpName(Type));
- if (asAddress)
- ILG.ConvertAddress(varType, Type);
- else
- ILG.ConvertValue(varType, Type);
- varType = Type;
- }
- Convert(varType, elementType, asAddress);
- }
- }
- }
- private void Convert(Type sourceType, Type targetType, bool asAddress) {
- if (targetType != null) {
- if (asAddress)
- ILG.ConvertAddress(sourceType, targetType);
- else
- ILG.ConvertValue(sourceType, targetType);
- }
- }
- private void ConvertNullableValue(Type nullableType, Type targetType) {
- System.Diagnostics.Debug.Assert(targetType == nullableType || targetType.IsAssignableFrom(nullableType.GetGenericArguments()[0]));
- if (targetType != nullableType) {
- MethodInfo Nullable_get_Value = nullableType.GetMethod(
- "get_Value",
- CodeGenerator.InstanceBindingFlags,
- null,
- CodeGenerator.EmptyTypeArray,
- null
- );
- ILG.Call(Nullable_get_Value);
- if (targetType != null) {
- ILG.ConvertValue(Nullable_get_Value.ReturnType, targetType);
- }
- }
- }
- public static implicit operator string(SourceInfo source) {
- return source.Source;
- }
- public static bool operator !=(SourceInfo a, SourceInfo b) {
- if ((object)a != null)
- return !a.Equals(b);
- return (object)b != null;
- }
- public static bool operator ==(SourceInfo a, SourceInfo b) {
- if ((object)a != null)
- return a.Equals(b);
- return (object)b == null;
- }
- public override bool Equals(object obj) {
- if (obj == null)
- return Source == null;
- SourceInfo info = obj as SourceInfo;
- if (info != null)
- return Source == info.Source;
- return false;
- }
- public override int GetHashCode() {
- return (Source == null) ? 0 : Source.GetHashCode();
- }
- }
- }
|