public DynamicMetaObject MakeCallExpression(OverloadResolverFactory resolverFactory, MethodInfo method, params DynamicMetaObject[] parameters) { OverloadResolver resolver; if (method.IsStatic) { resolver = resolverFactory.CreateOverloadResolver(parameters, new CallSignature(parameters.Length), CallTypes.None); } else { resolver = resolverFactory.CreateOverloadResolver(parameters, new CallSignature(parameters.Length - 1), CallTypes.ImplicitInstance); } BindingTarget target = resolver.ResolveOverload(method.Name, new MethodBase[] { method }, NarrowingLevel.None, NarrowingLevel.All); if (!target.Success) { BindingRestrictions restrictions = BindingRestrictions.Combine(parameters); foreach (DynamicMetaObject mo in parameters) { restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(mo.Expression, mo.GetLimitType())); } return(DefaultBinder.MakeError( resolver.MakeInvalidParametersError(target), restrictions, typeof(object) )); } return(new DynamicMetaObject(target.MakeExpression(), target.RestrictedArguments.GetAllRestrictions())); }
public DynamicMetaObject DoOperation(ExpressionType operation, OverloadResolverFactory resolverFactory, params DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(resolverFactory, nameof(resolverFactory)); ContractUtils.RequiresNotNullItems(args, nameof(args)); return(MakeGeneralOperatorRule(operation, resolverFactory, args)); // Then try comparison / other ExpressionType }
private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args) { if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All)) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (oper == IndexType.Get) { return(new DynamicMetaObject( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), restrictions )); } return(new DynamicMetaObject( Expression.Assign( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType()) ), restrictions.Merge(args[1].Restrictions) )); } return(null); }
protected override DynamicMetaObject SetBoundValue(OverloadResolverFactory factory, ActionBinder binder, Type type, DynamicMetaObject value, DynamicMetaObject instance, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Condition( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.SlotTrySetValue)), ((PythonOverloadResolverFactory)factory)._codeContext, AstUtils.Constant(GetSlot(), typeof(PythonTypeSlot)), AstUtils.Convert( instance.Expression, typeof(object) ), AstUtils.Constant(DynamicHelpers.GetPythonTypeFromType(type)), value.Expression ), AstUtils.Convert(value.Expression, typeof(object)), errorSuggestion != null ? errorSuggestion.Expression : Expression.Throw( Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.AttributeErrorForMissingAttribute), new Type[] { typeof(object), typeof(string) }), instance.Expression, Expression.Constant(Name) ), typeof(object) ) ), BindingRestrictions.Empty )); }
/// <summary> /// Called when the user is accessing a protected or private member on a get. /// /// The default implementation allows access to the fields or properties using reflection. /// </summary> public virtual ErrorInfo MakeNonPublicMemberGetError(OverloadResolverFactory resolverFactory, MemberTracker member, Type type, DynamicMetaObject instance) { switch (member.MemberType) { case TrackerTypes.Field: FieldTracker ft = (FieldTracker)member; return(ErrorInfo.FromValueNoError( Ast.Call( AstUtils.Convert(AstUtils.Constant(ft.Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("GetValue"), AstUtils.Convert(instance.Expression, typeof(object)) ) )); case TrackerTypes.Property: PropertyTracker pt = (PropertyTracker)member; return(ErrorInfo.FromValueNoError( MemberTracker.FromMemberInfo(pt.GetGetMethod(true)).Call(resolverFactory, this, instance).Expression )); default: throw new InvalidOperationException(); } }
public GetMemberInfo(string name, OverloadResolverFactory resolutionFactory, bool noThrow, Expression errorSuggestion) { Name = name; ResolutionFactory = resolutionFactory; IsNoThrow = noThrow; ErrorSuggestion = errorSuggestion; }
/// <summary> /// Checks if there's a conversion to/from Nullable of T. /// </summary> private DynamicMetaObject TryNullableConversion(OverloadResolverFactory factory, Type toType, ConversionResultKind kind, Type knownType, BindingRestrictions restrictions, DynamicMetaObject arg) { if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (knownType == typeof(DynamicNull)) { // null -> Nullable<T> return(MakeNullToNullableOfTTarget(toType, restrictions)); } if (knownType == toType.GetGenericArguments()[0]) { return(MakeTToNullableOfTTarget(toType, knownType, restrictions, arg)); } if (kind != ConversionResultKind.ExplicitCast && kind != ConversionResultKind.ExplicitTry) { return(null); } if (knownType != typeof(object)) { // when doing an explicit cast we'll do things like int -> Nullable<float> return(MakeConvertingToTToNullableOfTTarget(factory, toType, kind, restrictions, arg)); } } return(null); }
private DynamicMetaObject MakeMetaMethodCall(CallSignature signature, OverloadResolverFactory resolverFactory, TargetInfo targetInfo) { BindingRestrictions restrictions = BindingRestrictions.Combine(targetInfo.Arguments).Merge(targetInfo.Restrictions); if (targetInfo.Instance != null) { restrictions = targetInfo.Instance.Restrictions.Merge(restrictions); } DynamicMetaObject[] args; CallTypes callType; if (targetInfo.Instance != null) { args = ArrayUtils.Insert(targetInfo.Instance, targetInfo.Arguments); callType = CallTypes.ImplicitInstance; } else { args = targetInfo.Arguments; callType = CallTypes.None; } return(CallMethod(resolverFactory.CreateOverloadResolver(args, signature, callType), targetInfo.Targets, restrictions)); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (target.HasValue && target.Value == null) { return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("Cannot call {0} method named {1} on nil", _isStatic ? "static" : "instance", this.Name))), typeof(object)), BindingRestrictions.GetInstanceRestriction(target.Expression, null))); } Type typeToUse = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType; IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length + (_isStatic ? 0 : 1)); if (!_isStatic) { argsPlus.Add(target); } foreach (DynamicMetaObject arg in args) { argsPlus.Add(arg); } OverloadResolverFactory factory = _context.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), _isStatic ? CallTypes.None : CallTypes.ImplicitInstance); BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | (_isStatic ? BindingFlags.Static : BindingFlags.Instance); IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetMethods(flags).Where <MethodBase>(x => x.Name == Name && x.GetParameters().Length == args.Length)); if (methods.Count > 0) { BindingTarget bt; DynamicMetaObject dmo = _context.Binder.CallMethod( res, methods, target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))), Name, NarrowingLevel.None, NarrowingLevel.All, out bt); dmo = DynUtils.MaybeBoxReturnValue(dmo); //; Console.WriteLine(dmo.Expression.DebugView); return(dmo); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("No matching member {0} taking {1} args for {2}", this.Name, args.Length, typeToUse.Name))), typeof(object)), target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))))); }
public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { Type typeToUse = target.Value is Type ? (Type)target.Value : target.LimitType; IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length); foreach (DynamicMetaObject arg in args) { argsPlus.Add(arg); } OverloadResolverFactory factory = _context.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), CallTypes.None); BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetConstructors(flags).Where <MethodBase>(x => x.GetParameters().Length == args.Length)); if (methods.Count > 0) { BindingTarget bt; DynamicMetaObject dmo = _context.Binder.CallMethod(res, methods, BindingRestrictions.Empty, "_ctor", NarrowingLevel.None, NarrowingLevel.All, out bt); dmo = DynUtils.MaybeBoxReturnValue(dmo); return(dmo); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant("Cannot find constructor matching args")), typeof(object)), target.Restrictions.Merge(BindingRestrictions.Combine(args)))); }
protected internal override DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance) { if (instance != null && IsStatic) { return(null); } if (GetIndexParameters().Length > 0) { // need to bind to a value or parameters to get the value. return(binder.ReturnMemberTracker(type, BindToInstance(instance))); } MethodInfo getter = GetGetMethod(true); if (getter == null || getter.ContainsGenericParameters) { // no usable getter return(null); } // TODO (tomat): this used to use getter.ReflectedType, is it still correct? getter = CompilerHelpers.TryGetCallableMethod(instance.GetLimitType(), getter); var defaultBinder = (DefaultBinder)binder; if (binder.PrivateBinding || CompilerHelpers.IsVisible(getter)) { return(defaultBinder.MakeCallExpression(resolverFactory, getter, instance)); } // private binding is just a call to the getter method... return(DefaultBinder.MakeError(defaultBinder.MakeNonPublicMemberGetError(resolverFactory, this, type, instance), BindingRestrictions.Empty, typeof(object))); }
/// <summary> /// Creates the MetaObject for indexing directly into arrays or indexing into objects which have /// default members. Returns null if we're not an indexing operation. /// </summary> public DynamicMetaObject SetIndex(OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { if (args[0].LimitType.IsArray) { return(MakeArrayIndexRule(resolverFactory, IndexType.Set, args)); } return(MakeMethodIndexRule(IndexType.Set, resolverFactory, args)); }
/// <summary> /// Select matching method from list based on args. /// </summary> /// <param name="targetType"></param> /// <param name="args"></param> /// <param name="methods"></param> /// <param name="methodName"></param> /// <param name="isStatic"></param> /// <returns></returns> private static MethodBase GetMatchingMethodAux(Type targetType, IList <HostArg> args, IList <MethodBase> methods, string methodName, bool isStatic) { int argCount = args.Count; if (methods.Count == 0) { return(null); } if (methods.Count == 1) { return(methods[0]); } IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(argCount + (isStatic ? 0 : 1)); if (!isStatic) { argsPlus.Add(new DynamicMetaObject(Expression.Default(targetType), BindingRestrictions.Empty)); } foreach (HostArg ha in args) { Expr e = ha.ArgExpr; Type argType = e.HasClrType ? (e.ClrType ?? typeof(object)) : typeof(Object); Type t; switch (ha.ParamType) { case HostArg.ParameterType.ByRef: t = typeof(System.Runtime.CompilerServices.StrongBox <>).MakeGenericType(argType); break; case HostArg.ParameterType.Standard: t = argType; break; default: throw Util.UnreachableCode(); } argsPlus.Add(new DynamicMetaObject(Expression.Default(t), BindingRestrictions.Empty)); } // TODO: See if we can get rid of .Default OverloadResolverFactory factory = ClojureContext.Default.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(argCount), isStatic ? CallTypes.None : CallTypes.ImplicitInstance); BindingTarget bt = res.ResolveOverload(methodName, methods, NarrowingLevel.None, NarrowingLevel.All); if (bt.Success) { return(bt.Overload.ReflectionInfo); } return(null); }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] // TODO: fix private DynamicMetaObject MakeOperatorRule(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { return (TryForwardOperator(info, resolverFactory, args) ?? TryReverseOperator(info, resolverFactory, args) ?? TryPrimitiveOperator(info, args) ?? TryMakeDefaultUnaryRule(info, args) ?? MakeOperatorError(info, args)); }
private DynamicMetaObject MakeMethodIndexRule(IndexType oper, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { MethodInfo[] defaults = GetMethodsFromDefaults(args[0].GetLimitType().GetDefaultMembers(), oper); if (defaults.Length != 0) { DynamicMetaObject[] selfWithArgs = args; ParameterExpression arg2 = null; if (oper == IndexType.Set) { Debug.Assert(args.Length >= 2); // need to save arg2 in a temp because it's also our result arg2 = Ast.Variable(args[2].Expression.Type, "arg2Temp"); args[2] = new DynamicMetaObject( Ast.Assign(arg2, args[2].Expression), args[2].Restrictions ); } BindingRestrictions restrictions = BindingRestrictions.Combine(args); var resolver = resolverFactory.CreateOverloadResolver(selfWithArgs, new CallSignature(selfWithArgs.Length), CallTypes.ImplicitInstance); BindingTarget target = resolver.ResolveOverload(oper == IndexType.Get ? "get_Item" : "set_Item", defaults, NarrowingLevel.None, NarrowingLevel.All); if (target.Success) { if (oper == IndexType.Get) { return(new DynamicMetaObject( target.MakeExpression(), restrictions.Merge(target.RestrictedArguments.GetAllRestrictions()) )); } else { return(new DynamicMetaObject( Ast.Block( new ParameterExpression[] { arg2 }, target.MakeExpression(), arg2 ), restrictions.Merge(target.RestrictedArguments.GetAllRestrictions()) )); } } return(MakeError( resolver.MakeInvalidParametersError(target), restrictions, typeof(object) )); } return(null); }
/// <summary> /// Checks if any conversions are available and if so builds the target for that conversion. /// </summary> private DynamicMetaObject TryAllConversions(OverloadResolverFactory factory, Type toType, ConversionResultKind kind, Type knownType, BindingRestrictions restrictions, DynamicMetaObject arg) { return (TryAssignableConversion(toType, knownType, restrictions, arg) ?? // known type -> known type TryExtensibleConversion(toType, knownType, restrictions, arg) ?? // Extensible<T> -> Extensible<T>.Value TryUserDefinedConversion(kind, toType, knownType, restrictions, arg) ?? // op_Implicit TryImplicitNumericConversion(toType, knownType, restrictions, arg) ?? // op_Implicit TryNullableConversion(factory, toType, kind, knownType, restrictions, arg) ?? // null -> Nullable<T> or T -> Nullable<T> TryNullConversion(toType, knownType, restrictions)); // null -> reference type }
/// <summary> /// Builds a MetaObject for performing a member get. Supports all built-in .NET members, the OperatorMethod /// GetBoundMember, and StrongBox instances. /// </summary> /// <param name="name"> /// The name of the member to retrieve. This name is not processed by the DefaultBinder and /// is instead handed off to the GetMember API which can do name mangling, case insensitive lookups, etc... /// </param> /// <param name="target"> /// The MetaObject from which the member is retrieved. /// </param> /// <param name="resolverFactory"> /// Provides overload resolution and method binding for any calls which need to be performed for the GetMember. /// </param> /// <returns> /// Returns a DynamicMetaObject which represents the value that will be returned when the member is accessed. /// /// The returned DynamicMetaObject may be strongly typed to a value type which needs boxing before being /// returned from a standard DLR GetMemberBinder. The language is responsible for performing any boxing /// so that it has an opportunity to perform custom boxing. /// </returns> public DynamicMetaObject GetMember(string name, DynamicMetaObject target, OverloadResolverFactory resolverFactory) { return(GetMember( name, target, resolverFactory, false, null )); }
private DynamicMetaObject TryComparisonMethod(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject target, DynamicMetaObject[] args) { MethodInfo[] targets = GetApplicableMembers(target.GetLimitType(), info); if (targets.Length > 0) { return(TryMakeBindingTarget(resolverFactory, targets, args, BindingRestrictions.Empty)); } return(null); }
private Expression ConvertIfNeeded(OverloadResolverFactory factory, Expression expression, Type type) { Assert.NotNull(expression, type); if (expression.Type != type) { return(ConvertExpression(expression, type, ConversionResultKind.ExplicitCast, factory)); } return(expression); }
private DynamicMetaObject TryForwardOperator(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { MethodInfo[] targets = GetApplicableMembers(args[0].GetLimitType(), info); BindingRestrictions restrictions = BindingRestrictions.Empty; if (targets.Length > 0) { return(TryMakeBindingTarget(resolverFactory, targets, args, restrictions)); } return(null); }
private DynamicMetaObject MakeComparisonRule(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { return (TryComparisonMethod(info, resolverFactory, args[0], args) ?? // check the first type if it has an applicable method TryComparisonMethod(info, resolverFactory, args[0], args) ?? // then check the second type TryNumericComparison(info, resolverFactory, args) ?? // try Compare: cmp(x,y) (>, <, >=, <=, ==, !=) 0 TryInvertedComparison(info, resolverFactory, args[0], args) ?? // try inverting the operator & result (e.g. if looking for Equals try NotEquals, LessThan for GreaterThan)... TryInvertedComparison(info, resolverFactory, args[0], args) ?? // inverted binding on the 2nd type TryNullComparisonRule(args) ?? // see if we're comparing to null w/ an object ref or a Nullable<T> TryPrimitiveCompare(info, args) ?? // see if this is a primitive type where we're comparing the two values. MakeOperatorError(info, args)); // no comparisons are possible }
private DynamicMetaObject TryReverseOperator(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { // we need a special conversion for the return type on MemberNames if (args.Length > 0) { MethodInfo[] targets = GetApplicableMembers(args[0].LimitType, info); if (targets.Length > 0) { return(TryMakeBindingTarget(resolverFactory, targets, args, BindingRestrictions.Empty)); } } return(null); }
public DynamicMetaObject DeleteMember(string name, DynamicMetaObject target, OverloadResolverFactory resolutionFactory, DynamicMetaObject errorSuggestion) { ContractUtils.RequiresNotNull(name, "name"); ContractUtils.RequiresNotNull(target, "target"); return(MakeDeleteMemberTarget( new SetOrDeleteMemberInfo( name, resolutionFactory ), target.Restrict(target.GetLimitType()), errorSuggestion )); }
protected override DynamicMetaObject GetBoundValue(OverloadResolverFactory factory, ActionBinder binder, Type type, DynamicMetaObject instance) { return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("SlotGetValue"), ((PythonOverloadResolverFactory)factory)._codeContext, AstUtils.Constant(GetSlot(), typeof(PythonTypeSlot)), AstUtils.Convert( instance.Expression, typeof(object) ), AstUtils.Constant(DynamicHelpers.GetPythonTypeFromType(type)) ), BindingRestrictions.Empty ); }
private DynamicMetaObject TryMakeInvertedBindingTarget(OverloadResolverFactory resolverFactory, MethodBase[] targets, DynamicMetaObject[] args) { var resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None); BindingTarget target = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All); if (target.Success) { return(new DynamicMetaObject( Expression.Not(target.MakeExpression()), target.RestrictedArguments.GetAllRestrictions() )); } return(null); }
private DynamicMetaObject MakeGeneratorOperatorRule(OverloadResolverFactory resolverFactory, DynamicMetaObject[] args, OperatorInfo info) { DynamicMetaObject res; if (CompilerHelpers.IsComparisonOperator(info.Operator)) { res = MakeComparisonRule(info, resolverFactory, args); } else { res = MakeOperatorRule(info, resolverFactory, args); } return(res); }
/// <summary> /// Builds a MetaObject for performing a member get. Supports all built-in .NET members, the OperatorMethod /// GetBoundMember, and StrongBox instances. /// </summary> /// <param name="name"> /// The name of the member to retrieve. This name is not processed by the DefaultBinder and /// is instead handed off to the GetMember API which can do name mangling, case insensitive lookups, etc... /// </param> /// <param name="target"> /// The MetaObject from which the member is retrieved. /// </param> /// <param name="resolverFactory"> /// An OverloadResolverFactory which can be used for performing overload resolution and method binding. /// </param> /// <param name="isNoThrow"> /// True if the operation should return Operation.Failed on failure, false if it /// should return the exception produced by MakeMissingMemberError. /// </param> /// <param name="errorSuggestion"> /// The meta object to be used if the get results in an error. /// </param> /// <returns> /// Returns a DynamicMetaObject which represents the value that will be returned when the member is accessed. /// /// The returned DynamicMetaObject may be strongly typed to a value type which needs boxing before being /// returned from a standard DLR GetMemberBinder. The language is responsible for performing any boxing /// so that it has an opportunity to perform custom boxing. /// </returns> public DynamicMetaObject GetMember(string name, DynamicMetaObject target, OverloadResolverFactory resolverFactory, bool isNoThrow, DynamicMetaObject errorSuggestion) { ContractUtils.RequiresNotNull(name, nameof(name)); ContractUtils.RequiresNotNull(target, nameof(target)); ContractUtils.RequiresNotNull(resolverFactory, nameof(resolverFactory)); return(MakeGetMemberTarget( new GetMemberInfo( name, resolverFactory, isNoThrow, errorSuggestion ), target )); }
private DynamicMetaObject TryInvertedComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject target, DynamicMetaObject[] args) { ExpressionType revOp = GetInvertedOperator(info.Operator); OperatorInfo revInfo = OperatorInfo.GetOperatorInfo(revOp); Debug.Assert(revInfo != null); // try the 1st type's opposite function result negated MethodBase[] targets = GetApplicableMembers(target.GetLimitType(), revInfo); if (targets.Length > 0) { return(TryMakeInvertedBindingTarget(resolverFactory, targets, args)); } return(null); }
/// <summary> /// Helper to produce the rule for converting T to Nullable of T /// </summary> private DynamicMetaObject MakeConvertingToTToNullableOfTTarget(OverloadResolverFactory resolverFactory, Type toType, ConversionResultKind kind, BindingRestrictions restrictions, DynamicMetaObject arg) { Type valueType = toType.GetGenericArguments()[0]; // ConvertSelfToT -> Nullable<T> if (kind == ConversionResultKind.ExplicitCast) { // if the conversion to T fails we just throw Expression conversion = ConvertExpression(arg.Expression, valueType, kind, resolverFactory); return(new DynamicMetaObject( Expression.New( toType.GetConstructor(new Type[] { valueType }), conversion ), restrictions )); } else { Expression conversion = ConvertExpression(arg.Expression, valueType, kind, resolverFactory); // if the conversion to T succeeds then produce the nullable<T>, otherwise return default(retType) ParameterExpression tmp = Expression.Variable(typeof(object), "tmp"); return(new DynamicMetaObject( Expression.Block( new ParameterExpression[] { tmp }, Expression.Condition( Expression.NotEqual( Expression.Assign(tmp, conversion), AstUtils.Constant(null) ), Expression.New( toType.GetConstructor(new Type[] { valueType }), Expression.Convert( tmp, valueType ) ), GetTryConvertReturnValue(toType) ) ), restrictions )); } }
protected internal override DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance) { if (IsPublic && DeclaringType.IsVisible) { return(new DynamicMetaObject( AstUtils.Convert( Expression.Field( AstUtils.Convert(instance.Expression, Field.DeclaringType), Field ), typeof(object) ), BindingRestrictions.Empty )); } return(DefaultBinder.MakeError(((DefaultBinder)binder).MakeNonPublicMemberGetError(resolverFactory, this, type, instance), BindingRestrictions.Empty, typeof(object))); }