/// <summary> /// Creates Func<object, T> depending on the access. /// </summary> Delegate CompileAccess(AccessMask access) { var pinstance = Expression.Parameter(typeof(object)); var expr = Bind(null, Expression.Convert(pinstance, _field.DeclaringType)); if (access == AccessMask.Read) { expr = ConvertExpression.BindToValue(expr); } else { expr = BinderHelpers.BindAccess(expr, null, access, null); } return(Expression.Lambda(expr, true, pinstance).Compile()); }
Delegate CompileAccess(AccessMask access) { var pctx = Expression.Parameter(typeof(Context)); var pinstance = Expression.Parameter(typeof(object)); var expr = Bind(pctx, Expression.Convert(pinstance, Field.DeclaringType)); if (access == AccessMask.Read) { expr = ConvertExpression.BindToValue(expr); } else { expr = BinderHelpers.BindAccess(expr, null, access, null); } // return(Expression.Lambda(expr, tailCall: true, parameters: new[] { pctx, pinstance }).Compile()); }
public ClrFieldProperty(PhpTypeInfo tinfo, FieldInfo field) : base(tinfo) { _field = field ?? throw new ArgumentNullException(nameof(field)); // _lazyGetter = new Lazy <Func <object, PhpValue> >(() => (Func <object, PhpValue>)CompileAccess(AccessMask.Read)); _lazyEnsureAlias = new Lazy <Func <object, PhpAlias> >(() => (Func <object, PhpAlias>)CompileAccess(AccessMask.ReadRef)); _lazyEnsureObject = new Lazy <Func <object, object> >(() => (Func <object, object>)CompileAccess(AccessMask.EnsureObject)); _lazyEnsureArray = new Lazy <Func <object, IPhpArray> >(() => (Func <object, IPhpArray>)CompileAccess(AccessMask.EnsureArray)); // SetValue(instance, PhpValue): void _lazySetValue = new Lazy <Action <Context, object, PhpValue> >(() => { if (IsReadOnly) { // error return(new Action <Context, object, PhpValue>((_, _instance, _value) => { PhpException.ErrorException(Resources.ErrResources.readonly_property_written, ContainingType.Name, PropertyName); })); } var pctx = Expression.Parameter(typeof(Context)); var pinstance = Expression.Parameter(typeof(object)); var pvalue = Expression.Parameter(typeof(PhpValue)); // expr: <instance>.<field> var expr = Bind(pctx, Expression.Convert(pinstance, _field.DeclaringType)); // expr: <field> := <value> expr = BinderHelpers.BindAccess(expr, pctx, AccessMask.Write, pvalue); // var lambda = Expression.Lambda(Expression.Block(expr, Expression.Empty()), pctx, pinstance, pvalue); return((Action <Context, object, PhpValue>)lambda.Compile()); }); }