예제 #1
0
 private CodeFunction FindCodeFunction(Project project, IBindingMethod bindingMethod)
 {
     return(GetBindingClassesIncludingPartialClasses(project)
            .Where(c => c.FullName == bindingMethod.Type.FullName)
            .SelectMany(c => c.GetFunctions()).FirstOrDefault(
                f => f.Name == bindingMethod.Name && BindingReflectionExtensions.MethodEquals(bindingMethod, new VsBindingMethod(f))));
 }
예제 #2
0
        private Expression GenerateMethodCall(MethodData method, ArgumentData target, IList <ArgumentData> args)
        {
            args = BindingReflectionExtensions.GetMethodArgs(method.IsExtensionMethod, target, args);
            var expressions = new Expression[args.Count];

            for (int index = 0; index < args.Count; index++)
            {
                var data = args[index];
                if (data.IsLambda)
                {
                    _lambdaParameter = method.Parameters[index];
                    data.UpdateExpression(BuildExpression(data.Node));
                    _lambdaParameter = null;
                }
                expressions[index] = data.Expression;
            }
            var methodInfo = method.Build(args);

            expressions = ConvertParameters(methodInfo, expressions);
            if (method.IsExtensionMethod)
            {
                return(Expression.Call(null, methodInfo, expressions));
            }
            return(Expression.Call(target.Expression, methodInfo, expressions));
        }
예제 #3
0
        private Expression TryGenerateMethodCall(IList <MethodData> methods, ArgumentData target, IList <ArgumentData> arguments)
        {
            if (methods == null || methods.Count == 0)
            {
                return(null);
            }

            var methodInfos = new List <MethodInfo>(methods.Count);
            var methodArgs  = new List <Expression[]>(methods.Count);

            for (int i = 0; i < methods.Count; i++)
            {
                try
                {
                    var method      = methods[i];
                    var args        = BindingReflectionExtensions.GetMethodArgs(method.IsExtensionMethod, target, arguments);
                    var expressions = new Expression[args.Count];
                    for (int index = 0; index < args.Count; index++)
                    {
                        var data = args[index];
                        if (data.IsLambda)
                        {
                            _lambdaParameter = method.Parameters[index];
                            data.UpdateExpression(BuildExpression(data.Node));
                            _lambdaParameter = null;
                        }
                        expressions[index] = data.Expression;
                    }
                    var methodInfo = method.Build(args);
                    if (methodInfo != null)
                    {
                        methodInfos.Add(methodInfo);
                        methodArgs.Add(expressions);
                    }
                }
                catch
                {
                    ;
                }
            }

            bool resultHasParams;
            var  resultIndex = TrySelectMethod(methodInfos, methodArgs, (i, args) => args[i].ToArrayEx(e => e.Type), out resultHasParams);

            if (resultIndex < 0)
            {
                return(null);
            }
            var result           = methodInfos[resultIndex];
            var resultArgs       = methodArgs[resultIndex];
            var resultParameters = result.GetParameters();

            resultArgs = ConvertParameters(resultParameters, resultArgs, resultHasParams);
            return(Expression.Call(result.IsExtensionMethod() ? null : target.Expression, result, resultArgs));
        }
예제 #4
0
        private Expression BuildMemberExpression(IMemberExpressionNode expression)
        {
            if (expression.Member.Contains("("))
            {
                return(BuildMethodCall(new MethodCallExpressionNode(expression.Target,
                                                                    expression.Member.Replace("(", string.Empty).Replace(")", string.Empty), null, null)));
            }
            if (expression.Target == null)
            {
                Expression value;
                if (!_lambdaParameters.TryGetValue(expression.Member, out value))
                {
                    throw BindingExceptionManager.UnexpectedExpressionNode(expression);
                }
                return(value);
            }

            var target = BuildExpression(expression.Target);
            var type   = GetTargetType(ref target);
            var @enum  = BindingReflectionExtensions.TryParseEnum(expression.Member, type);

            if (@enum != null)
            {
                return(Expression.Constant(@enum));
            }

            if (type != null)
            {
                var bindingMember = BindingServiceProvider
                                    .MemberProvider
                                    .GetBindingMember(type, expression.Member, false, false);
                if (bindingMember != null)
                {
                    var methodCall = Expression.Call(Expression.Constant(bindingMember, typeof(IBindingMemberInfo)),
                                                     BindingMemberGetValueMethod,
                                                     ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false),
                                                     EmptyObjectArrayExpression);
                    return(Expression.Convert(methodCall, bindingMember.Type));
                }
            }

            var member = type.FindPropertyOrField(expression.Member, target == null);

            //Trying to get dynamic value.
            if (member == null)
            {
                return(Expression.Call(null, GetMemberValueDynamicMethod,
                                       ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false),
                                       Expression.Constant(expression.Member, typeof(string))));
            }
            return(member is PropertyInfo
                ? Expression.Property(target, (PropertyInfo)member)
                : Expression.Field(target, (FieldInfo)member));
        }
예제 #5
0
        private static bool IsAssignableFrom(Type attachedMemberType, Type sourceType)
        {
#if PCL_WINRT
            if (attachedMemberType.GetTypeInfo().IsGenericTypeDefinition&&
                BindingReflectionExtensions.FindCommonType(attachedMemberType, sourceType) != null)
#else
            if (attachedMemberType.IsGenericTypeDefinition &&
                BindingReflectionExtensions.FindCommonType(attachedMemberType, sourceType) != null)
#endif
            { return(true); }
            return(attachedMemberType.IsAssignableFrom(sourceType));
        }
예제 #6
0
        public BindingMemberInfo(IBindingMemberInfo attachedIndexerMember, string path)
        {
            var accessor = new AttachedIndexerAccessor(attachedIndexerMember, BindingReflectionExtensions.GetIndexerValues(path, castType: typeof(string)));

            _getValueAccessor             = accessor.GetValue;
            _setValueAccessor             = accessor.SetValue;
            _indexerAttachedBindingMember = attachedIndexerMember;
            _memberType = attachedIndexerMember.MemberType;
            _type       = attachedIndexerMember.Type;
            _canRead    = attachedIndexerMember.CanRead;
            _canWrite   = attachedIndexerMember.CanWrite;
            _canObserve = attachedIndexerMember.CanObserve;
        }
예제 #7
0
        public BindingMemberInfo(string path, Type type)
            : this(path, BindingMemberType.Array, type.GetElementType())
        {
            var indexes = BindingReflectionExtensions
                          .GetIndexerValues(path, null, typeof(int))
                          .ToArrayEx(o => (int)o);
            var arrayAccessor = new ArrayAccessor(indexes);

            _getValueAccessorSingle       = arrayAccessor.GetValue;
            _setValueAccessorSingleAction = arrayAccessor.SetValue;
            _canRead           = true;
            _canWrite          = true;
            _isSingleParameter = true;
        }
예제 #8
0
 public BindingMemberInfo(string path, bool expandoObject)
     : this(path, BindingMemberType.Dynamic, typeof(object))
 {
     object[] indexerValues = null;
     if (expandoObject)
     {
         _isSingleParameter      = true;
         _getValueAccessorSingle = o =>
         {
             object value;
             ((IDictionary <string, object>)o).TryGetValue(path, out value);
             return(value);
         };
         _setValueAccessorSingleAction = (o, v) => ((IDictionary <string, object>)o)[path] = v;
     }
     else
     {
         if (path.StartsWith("[", StringComparison.Ordinal) || path.StartsWith("Item[", StringComparison.Ordinal))
         {
             indexerValues = BindingReflectionExtensions.GetIndexerValues(path, castType: typeof(string));
         }
         var accessor = new DynamicObjectAccessor(path, indexerValues);
         if (indexerValues == null)
         {
             _getValueAccessor = accessor.GetValue;
             _setValueAccessor = accessor.SetValue;
         }
         else
         {
             _getValueAccessor = accessor.GetValueIndex;
             _setValueAccessor = accessor.SetValueIndex;
         }
         _isDynamic  = true;
         _canObserve = true;
     }
     _canRead  = true;
     _canWrite = true;
 }
예제 #9
0
        public object Invoke(IDataContext context, IList <object> sourceValues)
        {
            var key = new CacheKey(sourceValues.ToArrayEx(o => o == null ? null : o.GetType()));
            Func <object[], object> expression;

            lock (_expressionCache)
            {
                if (!_expressionCache.TryGetValue(key, out expression))
                {
                    try
                    {
                        _sourceValues = sourceValues;
                        _parameters   = new List <KeyValuePair <int, ParameterExpression> >
                        {
                            new KeyValuePair <int, ParameterExpression>(-1, DataContextParameter)
                        };
                        _dataContext          = context;
                        expression            = CreateDelegate();
                        _expressionCache[key] = expression;
                    }
                    finally
                    {
                        _lambdaParameter = null;
                        _lambdaParameters.Clear();
                        _sourceValues = null;
                        _parameters   = null;
                        _dataContext  = null;
                    }
                }
            }
            if (_isEmpty)
            {
                return(expression.Invoke(new object[] { context }));
            }
            return(expression.Invoke(BindingReflectionExtensions.InsertFirstArg(sourceValues, context)));
        }
예제 #10
0
        protected virtual IBindingMemberInfo GetExplicitBindingMember([NotNull] Type sourceType, [NotNull] string path)
        {
            path = path.Trim();
            if (typeof(IDynamicObject).IsAssignableFrom(sourceType) && path != AttachedMemberConstants.DataContext)
            {
                return(new BindingMemberInfo(path));
            }

            int indexerCounts = 0;

            if (path.StartsWith("[") && path.EndsWith("]"))
            {
                indexerCounts = 1;
                for (int index = 0; index < path.Length; index++)
                {
                    if (path[index] == ',')
                    {
                        indexerCounts++;
                    }
                }
            }

            var types = BindingReflectionExtensions.SelfAndBaseTypes(sourceType);

            foreach (var type in types)
            {
                if (indexerCounts == 0)
                {
                    PropertyInfo property = type.GetPropertyEx(path, PropertyFlags);
                    if (property != null)
                    {
                        return(new BindingMemberInfo(path, property, sourceType));
                    }
                }
                else
                {
                    PropertyInfo property = type
                                            .GetPropertiesEx(PropertyFlags)
                                            .FirstOrDefault(info => info.GetIndexParameters().Length == indexerCounts);
                    if (property != null)
                    {
                        return(new BindingMemberInfo(path, property, sourceType));
                    }

                    if (type.IsArray && type.GetArrayRank() == indexerCounts)
                    {
                        return(new BindingMemberInfo(path, type));
                    }
                }
                EventInfo @event = type.GetEventEx(path, EventFlags);
                if (@event != null)
                {
                    return(new BindingMemberInfo(path, @event));
                }

                FieldInfo field = type.GetFieldEx(path, FieldFlags);
                if (field != null)
                {
                    return(new BindingMemberInfo(path, field, sourceType));
                }
            }
            return(null);
        }
예제 #11
0
            private object InvokeMethodInternal(object target, string methodName, object[] args, Type[] typeArgs)
            {
                var type     = target.GetType();
                var argTypes = GetArgTypes(args);
                var key      = new CacheKey(argTypes);
                Func <object[], object> result = null;

                lock (this)
                {
                    if (type == _type)
                    {
                        TryGetValue(key, out result);
                    }
                }
                if (result != null)
                {
                    return(result(BindingReflectionExtensions.InsertFirstArg(args, target)));
                }

                List <MethodInfo> methods;

                if (methodName == ReflectionExtensions.IndexerName)
                {
                    methods = new List <MethodInfo>();
                    foreach (var property in type.GetPropertiesEx(MemberFlags.Public | MemberFlags.Instance))
                    {
                        if (property.GetIndexParameters().Length == args.Length)
                        {
                            methods.AddIfNotNull(property.GetGetMethod(true));
                        }
                    }
                }
                else
                {
                    methods = BindingReflectionExtensions.GetExtensionsMethods(methodName, BindingServiceProvider.ResourceResolver.GetKnownTypes());
                    foreach (var method in type.GetMethodsEx(MemberFlags.Public | MemberFlags.Instance))
                    {
                        try
                        {
                            if (method.Name == methodName)
                            {
                                methods.AddIfNotNull(BindingReflectionExtensions.ApplyTypeArgs(method, typeArgs));
                            }
                        }
                        catch
                        {
                            ;
                        }
                    }
                }
                bool hasParams;
                var  resultIndex = TrySelectMethod(methods, argTypes, (i, types) => types, out hasParams);

                if (resultIndex >= 0)
                {
                    var method         = methods[resultIndex];
                    var parameters     = argTypes.Select(t => (Expression)Expression.Parameter(t)).ToList();
                    var argExpressions = ConvertParameters(method.GetParameters(), parameters, hasParams);
                    parameters.Insert(0, Expression.Parameter(type));
                    var compile    = Expression.Lambda(Expression.Call(parameters[0], method, argExpressions), parameters.Cast <ParameterExpression>()).Compile();
                    var methodInfo = compile.GetType().GetMethodEx(nameof(Action.Invoke), MemberFlags.Public | MemberFlags.Instance);
                    if (methodInfo == null)
                    {
                        result = compile.DynamicInvoke;
                    }
                    else
                    {
                        var del = ServiceProvider.ReflectionManager.GetMethodDelegate(methodInfo);
                        result = objects => del(compile, objects);
                    }
                }
                lock (this)
                {
                    _type     = type;
                    this[key] = result;
                }
                if (result == null)
                {
                    throw BindingExceptionManager.InvalidBindingMember(target.GetType(), methodName);
                }
                return(result(BindingReflectionExtensions.InsertFirstArg(args, target)));
            }
예제 #12
0
        protected virtual IBindingMemberInfo GetExplicitBindingMember([NotNull] Type sourceType, [NotNull] string path)
        {
            path = path.Trim();
            string[] indexerArgs = null;
            if (path.StartsWith("[", StringComparison.Ordinal) && path.EndsWith("]", StringComparison.Ordinal))
            {
                indexerArgs = path
                              .RemoveBounds()
                              .Split(BindingReflectionExtensions.CommaSeparator, StringSplitOptions.RemoveEmptyEntries);
            }

            var types = BindingReflectionExtensions.SelfAndBaseTypes(sourceType);

            foreach (var type in types)
            {
                if (indexerArgs == null)
                {
                    PropertyInfo property = type.GetPropertyEx(path, PropertyFlags);
                    if (property != null)
                    {
                        return(new BindingMemberInfo(path, property, sourceType));
                    }
                }
                else
                {
                    PropertyInfo candidate      = null;
                    int          valueTypeCount = -1;
                    foreach (var property in type.GetPropertiesEx(PropertyFlags))
                    {
                        var indexParameters = property.GetIndexParameters();
                        if (indexParameters.Length != indexerArgs.Length)
                        {
                            continue;
                        }
                        try
                        {
                            int count = 0;
                            for (int i = 0; i < indexParameters.Length; i++)
                            {
                                var arg       = indexerArgs[i];
                                var paramType = indexParameters[i].ParameterType;
                                if (arg.StartsWith("\"", StringComparison.Ordinal) && arg.EndsWith("\"", StringComparison.Ordinal))
                                {
                                    if (paramType != typeof(string))
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    BindingServiceProvider.ValueConverter(Empty, paramType, arg);
                                    if (paramType.IsValueType())
                                    {
                                        count++;
                                    }
                                }
                            }
                            if (valueTypeCount < count)
                            {
                                candidate      = property;
                                valueTypeCount = count;
                            }
                        }
                        catch
                        {
                            ;
                        }
                    }
                    if (candidate != null)
                    {
                        return(new BindingMemberInfo(path, candidate, sourceType));
                    }
                    if (type.IsArray && type.GetArrayRank() == indexerArgs.Length)
                    {
                        return(new BindingMemberInfo(path, type));
                    }
                }
                EventInfo @event = type.GetEventEx(path, EventFlags);
                if (@event != null)
                {
                    return(new BindingMemberInfo(path, @event, null));
                }

                FieldInfo field = type.GetFieldEx(path, FieldFlags);
                if (field != null)
                {
                    return(new BindingMemberInfo(path, field, sourceType));
                }
            }

            if (typeof(IDynamicObject).IsAssignableFrom(sourceType))
            {
                return(new BindingMemberInfo(path, false));
            }
            if (typeof(ExpandoObject).IsAssignableFrom(sourceType))
            {
                return(new BindingMemberInfo(path, true));
            }


            if (path.EndsWith(AttachedMemberConstants.ChangedEventPostfix, StringComparison.Ordinal))
            {
                var memberName = path.Substring(0, path.Length - 7);
                var member     = GetBindingMember(sourceType, memberName, false, false);
                if (member != null && member.CanObserve)
                {
                    return(new BindingMemberInfo(path, null, member));
                }
            }
            return(null);
        }
예제 #13
0
 public object SetValue(object src, object[] args)
 {
     return(_member.SetValue(src, BindingReflectionExtensions.InsertFirstArg(args ?? MugenMvvmToolkit.Empty.Array <object>(), _indexes)));
 }