private static void EmitGetter(ILGenerator getGenerator, Type targetType, string propertyName) { var privateGetMethod = CompatTypeExtensions.GetMethod(targetType, "get_" + propertyName); if (privateGetMethod != null) { getGenerator.DeclareLocal(typeof(object)); //Load the first argument getGenerator.Emit(OpCodes.Ldarg_1); //Cast to the source type getGenerator.Emit(OpCodes.Castclass, targetType); //Get the property value getGenerator.EmitCall(OpCodes.Call, privateGetMethod, null); if (privateGetMethod.ReturnType.GetTypeInfo().IsValueType) { //Box getGenerator.Emit(OpCodes.Box, privateGetMethod.ReturnType); } //Store it // following IL seems unnecessary according to test results // original source contained the following 2 lines // getGenerator.Emit(OpCodes.Stloc_0); // getGenerator.Emit(OpCodes.Ldloc_0); } else { getGenerator.ThrowException(typeof(MissingMethodException)); } getGenerator.Emit(OpCodes.Ret); }
internal DynamicPropertyAccessor(Type targetType, string propertyName) { TargetType = targetType; PropertyName = propertyName; var propertyInfo = CompatTypeExtensions.GetProperty(targetType, propertyName); if (propertyInfo == null) { throw new TypeEmitterException(string.Format($"Property \"{propertyName}\" is not found in type \"{targetType}\".", propertyName, targetType)); } CanRead = propertyInfo.CanRead; CanWrite = propertyInfo.CanWrite; PropertyType = propertyInfo.PropertyType; PropertyDelegate = PropertyDelegateFactory.CreateAccessor(targetType, propertyName); }
private static void EmitSetter(ILGenerator setGenerator, Type targetType, string propertyName) { var privateSetMethod = CompatTypeExtensions.GetMethod(targetType, "set_" + propertyName); if (privateSetMethod != null) { Type paramType = privateSetMethod.GetParameters()[0].ParameterType; setGenerator.DeclareLocal(paramType); //Load the first argument //(target object) setGenerator.Emit(OpCodes.Ldarg_1); //Cast to the source type setGenerator.Emit(OpCodes.Castclass, targetType); //Load the second argument setGenerator.Emit(OpCodes.Ldarg_2); //(value object) if (paramType.GetTypeInfo().IsValueType) { //Unbox it setGenerator.Emit(OpCodes.Unbox, paramType); //and load if (TypeOpCodeMapping.Map.TryGetValue(paramType, out var code)) { var load = code; setGenerator.Emit(load); } else { setGenerator.Emit(OpCodes.Ldobj, paramType); } } else { setGenerator.Emit(OpCodes.Castclass, paramType); //Cast class } setGenerator.EmitCall(OpCodes.Callvirt, privateSetMethod, null); //Set the property value } else { setGenerator.ThrowException(typeof(MissingMethodException)); } setGenerator.Emit(OpCodes.Ret); }
public static IDynamicPropertyAccessor Create <TType>(Expression <Func <TType, object> > propertyExpression) { if (propertyExpression == null) { throw new ArgumentException($"{nameof(propertyExpression)}", nameof(propertyExpression)); } if (propertyExpression.Body == null) { throw new ArgumentException($"{nameof(propertyExpression)}.{nameof(propertyExpression.Body)}", nameof(propertyExpression)); } var bodyType = propertyExpression.Body.GetType(); MemberExpression memberExpression; if (typeof(UnaryExpression) == bodyType) { var unary = propertyExpression.Body as UnaryExpression; memberExpression = unary.Operand as MemberExpression; if (memberExpression == null) { throw new NotSupportedException(string.Format($"{nameof(UnaryExpression)} only support {nameof(MemberExpression)} at this point. {0}", unary.Operand.GetType())); } return(new DynamicPropertyAccessor(typeof(TType), memberExpression.Member.Name)); } else if (CompatTypeExtensions.IsAssignableFrom(typeof(MemberExpression), bodyType)) { memberExpression = propertyExpression.Body as MemberExpression; if (memberExpression == null) { throw new ArgumentException(nameof(memberExpression), nameof(memberExpression)); } return(Create(typeof(TType), memberExpression.Member.Name)); } else { throw new NotSupportedException($"{bodyType} not supported."); } }