private void EmitObjectConverter(ILGenerator il, Type inType, Type outType) { var outProps = outType.GetProperties(); var inProps = inType.GetProperties(); var casted = il.DeclareLocal(inType); var converted = il.DeclareLocal(outType); var v2 = il.DeclareLocal(outType); var v3 = il.DeclareLocal(objectType); var brLabel = il.DefineLabel(); var returnType = !outType.IsInterface ? outType : inType; //var casted = (IModel1<...>) @in; il.Ldarg(1); il.Castclass(inType); il.Stloc(casted); //return new Model1<...> var returnConstructor = returnType.GetConstructor(Type.EmptyTypes); il.Newobj(returnConstructor); il.Stloc(v2); for (var i = 0; i < outProps.Length; i++) { var inProp = inProps[i]; var outProp = outProps[i]; if (!outType.IsInterface && inProp.PropertyType != outProp.PropertyType) { //OutProp = (OutPropType)ConverterStorage.Instance.GetImplementation(casted.InProp.GetType(), casted.OutProp.GetType()).Convert(casted.InProp) il.Ldloc(v2); il.Ldsfld(ConverterStorage.InstanceFieldInfo); il.Ldtoken(inProp.PropertyType); il.Call(typeOfMethodInfo); il.Ldtoken(outProp.PropertyType); il.Call(typeOfMethodInfo); il.Callvirt(ConverterStorage.GetImplementationFieldInfo); il.Ldloc(casted); il.Callvirt(inProp.GetMethod); il.Callvirt(convertMethodInfo); il.Castclass(outProp.PropertyType); il.Callvirt(outProp.SetMethod); continue; } //Prop1 = casted.Prop1, il.Ldloc(v2); il.Ldloc(casted); il.Callvirt(inProp.GetMethod); il.Callvirt(!outType.IsInterface ? outProp.SetMethod : inProp.SetMethod); } il.Ldloc(v2); il.Stloc(converted); il.Ldloc(converted); il.Stloc(v3); il.BrS(brLabel); il.MarkLabel(brLabel); il.Ldloc(v3); il.Ret(); }
private void EmitStructConverter(ILGenerator il, Type inType, Type outType) { var casted = il.DeclareLocal(inType); var converted = il.DeclareLocal(outType); var v2 = il.DeclareLocal(objectType); var inPropMap = inType.GetProperties().ToDictionary(x => x.Name.ToLower()); var outCtor = outType.GetConstructors().OrderByDescending(x => x.GetParameters().Length).First(); var ctorParamMap = outCtor .GetParameters() .Select(outParam => { var outParamKey = outParam.Name.ToLower(); return(new { outParam, inProp = inPropMap.ContainsKey(outParamKey) ? inPropMap[outParamKey] : null }); }) .ToArray(); var invalidParamTransitions = ctorParamMap.Where(x => x.inProp == null).ToArray(); if (invalidParamTransitions.Length > 0) { throw new Exception($"Can't serialize this kind of struct. Need to know how to map next ctor params: {string.Join(", ", invalidParamTransitions.Select(x => x.outParam.Name))}"); } il.Ldarg(1); il.Unbox_Any(inType); il.Stloc(casted); il.Ldloca(converted); foreach (var ctorParamPair in ctorParamMap) { var inItem = ctorParamPair.inProp; var outItem = ctorParamPair.outParam; var inItemType = inItem.PropertyType; var outItemType = outItem.ParameterType; if (inItemType == outItemType) { il.Ldloca(casted); il.Call(inItem.GetMethod); } else { il.Ldsfld(ConverterStorage.InstanceFieldInfo); il.Ldtoken(inItemType); il.Call(typeOfMethodInfo); il.Ldtoken(outItemType); il.Call(typeOfMethodInfo); il.Callvirt(ConverterStorage.GetImplementationFieldInfo); il.Ldloca(casted); il.Call(inItem.GetMethod); il.Callvirt(convertMethodInfo); il.Castclass(outItemType); } } il.Call(outCtor); il.Ldloc(converted); il.Box(outType); il.Stloc(v2); var brLabel = il.DefineLabel(); il.BrS(brLabel); il.MarkLabel(brLabel); il.Ldloc(v2); il.Ret(); }
private void EmitCollectionConverter(ILGenerator il, Type inType, Type outType) { if ((inType.IsIEnumerableInterface() || inType.IsIEnumerableInterfaceImplementation()) && outType.IsArray) { var inItemType = inType.GetEnumerableType(); var outItemType = outType.GetElementType(); if (inItemType != outItemType) { var casted = il.DeclareLocal(inType); var converted = il.DeclareLocal(outType); var v2 = il.DeclareLocal(objectType); il.Ldarg(1); il.Castclass(inType); il.Stloc(casted); il.Ldloc(casted); il.Call(collectionConverterInfo.MakeGenericMethod(inItemType, outItemType)); il.Stloc(converted); il.Ldloc(converted); il.Stloc(v2); var ret = il.DefineLabel(); il.BrS(ret); il.MarkLabel(ret); il.Ldloc(v2); il.Ret(); } else { var casted = il.DeclareLocal(inType); var array = il.DeclareLocal(inItemType.MakeArrayType()); var v2 = il.DeclareLocal(objectType); il.Ldarg(1); il.Castclass(inType); il.Stloc(casted); il.Ldloc(casted); il.Call(typeof(Enumerable).GetMethod("ToArray").MakeGenericMethod(inItemType)); il.Stloc(array); il.Ldloc(array); il.Stloc(v2); var ret = il.DefineLabel(); il.BrS(ret); il.MarkLabel(ret); il.Ldloc(v2); il.Ret(); } } else { var inItemType = inType.GetElementType(); var outItemType = outType.GetEnumerableType(); if (inItemType != outItemType) { var casted = il.DeclareLocal(typeof(IEnumerable <>).MakeGenericType(inItemType)); var converted = il.DeclareLocal(outType); var v2 = il.DeclareLocal(objectType); il.Ldarga(1); il.Castclass(inType); il.Stloc(casted); il.Ldloc(casted); il.Call(collectionConverterInfo.MakeGenericMethod(inItemType, outItemType)); il.Stloc(converted); il.Ldloc(converted); il.Stloc(v2); var ret = il.DefineLabel(); il.BrS(ret); il.MarkLabel(ret); il.Ldloc(v2); il.Ret(); } else { var v0 = il.DeclareLocal(objectType); il.Ldarg(1); il.Castclass(inType); il.Stloc(v0); var ret = il.DefineLabel(); il.BrS(ret); il.MarkLabel(ret); il.Ldloc(v0); il.Ret(); } } }