Beispiel #1
0
        private Type ProcessResultIdentifier(CsIdentifier identifier, Type parentType = null)
        {
            MemberResult memberResult;

            if (parentType != null)
            {
                var previousType = objType;

                objType      = parentType;
                memberResult = ProcessIdentifier(identifier);
                objType      = previousType;
            }
            else
            {
                memberResult = ProcessIdentifier(identifier);
                methodGenerator.Emit(OpCodes.Ldarg_1);
            }

            if (memberResult.IsField)
            {
                if (memberResult.IsPublic)
                {
                    methodGenerator.Emit(OpCodes.Ldfld, memberResult.Field);
                }
                else
                {
                    CallGetPrivateField(memberResult);
                }

                if (memberResult.IsBoxType)
                {
                    methodGenerator.Emit(OpCodes.Box, memberResult.Type);
                }

                return(memberResult.Type);
            }
            else if (memberResult.IsProperty)
            {
                if (memberResult.IsPublic)
                {
                    var property = memberResult.Property;
                    var method   = property.GetGetMethod();

                    methodGenerator.EmitCall(OpCodes.Callvirt, method, null);
                }
                else
                {
                    CallGetPrivateProperty(memberResult);
                }

                if (memberResult.IsBoxType)
                {
                    methodGenerator.Emit(OpCodes.Box, memberResult.Type);
                }

                return(memberResult.Type);
            }

            return(null);
        }
Beispiel #2
0
        private MemberResult ProcessIdentifier(CsIdentifier identifier)
        {
            var result    = new MemberResult();
            var fieldInfo = itemType.GetField(identifier.original_text, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);

            if (fieldInfo != null)
            {
                result.MemberInfo = fieldInfo;
                result.IsPublic   = fieldInfo.IsPublic;
            }
            else
            {
                var propertyInfo = itemType.GetProperty(identifier.original_text, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty);

                if (propertyInfo != null)
                {
                    var getMethod = propertyInfo.GetGetMethod();

                    result.MemberInfo = propertyInfo;

                    if (getMethod == null)
                    {
                        getMethod = propertyInfo.GetGetMethod(true);
                    }

                    result.IsPublic = getMethod.IsPublic;
                }
                else
                {
                    Debugger.Break();
                }
            }

            return(result);
        }
Beispiel #3
0
        internal ResolveContext ResolveSimpleName(CsIdentifier simpleName, ResolveContext context = null)
        {
            if (context is ResolveContextMethodGroup)
            {
                throw new NotImplementedException("Access to method groups is not supported.");
            }

            var simpleNameBuiltin = simpleName as CsKeywordIdentifier;

            if (simpleNameBuiltin != null)
            {
                if (context != null)
                {
                    throw new InvalidOperationException("Unexpected built-in: {0}.".Fmt(simpleNameBuiltin.ToString()));
                }

                switch (simpleNameBuiltin.Keyword)
                {
                case "string": return(new ResolveContextType(typeof(string)));

                case "sbyte": return(new ResolveContextType(typeof(sbyte)));

                case "byte": return(new ResolveContextType(typeof(byte)));

                case "short": return(new ResolveContextType(typeof(short)));

                case "ushort": return(new ResolveContextType(typeof(ushort)));

                case "int": return(new ResolveContextType(typeof(int)));

                case "uint": return(new ResolveContextType(typeof(uint)));

                case "long": return(new ResolveContextType(typeof(long)));

                case "ulong": return(new ResolveContextType(typeof(ulong)));

                case "object": return(new ResolveContextType(typeof(object)));

                case "bool": return(new ResolveContextType(typeof(bool)));

                case "char": return(new ResolveContextType(typeof(char)));

                case "float": return(new ResolveContextType(typeof(float)));

                case "double": return(new ResolveContextType(typeof(double)));

                case "decimal": return(new ResolveContextType(typeof(decimal)));

                case "this":
                    if (_currentInstance == null)
                    {
                        throw new InvalidOperationException("Cannot use ‘this’ pointer when no current instance exists.");
                    }
                    return(new ResolveContextConstant(_currentInstance));

                case "base":
                    throw new InvalidOperationException("Base method calls are not supported.");

                default:
                    throw new InvalidOperationException("Unexpected built-in: {0}.".Fmt(simpleNameBuiltin.ToString()));
                }
            }

            var simpleNameIdentifier = simpleName as CsNameIdentifier;

            if (simpleNameIdentifier == null)
            {
                throw new InvalidOperationException("Unexpected simple-name type: {0}.".Fmt(simpleName.GetType().FullName));
            }

            // Is it a local?
            if (context == null && _localNames.ContainsKey(simpleNameIdentifier.Name))
            {
                return(_localNames[simpleNameIdentifier.Name]);
            }

            List <string> candidatePrefixes = new List <string>();

            if (context is ResolveContextNamespace)
            {
                candidatePrefixes.Add(((ResolveContextNamespace)context).Namespace);
            }
            else if ((context == null && _currentNamespace == null) || context is ResolveContextGlobal)
            {
                candidatePrefixes.Add(null);
            }
            else if (context == null)
            {
                candidatePrefixes.Add(null);
                string soFar = null;
                foreach (var part in _currentNamespace.Split('.'))
                {
                    soFar += (soFar == null ? "" : ".") + part;
                    candidatePrefixes.Add(soFar);
                }
                candidatePrefixes.AddRange(_usingNamespaces);
            }

            // Is it a namespace?
            if (simpleNameIdentifier.GenericTypeArguments == null && (context == null || context is ResolveContextNamespace) && _assemblies != null)
            {
                foreach (var prefix in candidatePrefixes)
                {
                    var prefixWithName    = prefix == null ? simpleNameIdentifier.Name : prefix + "." + simpleNameIdentifier.Name;
                    var typeWithNamespace = _assemblies.SelectMany(a => a.GetTypes()).FirstOrDefault(t => t.Namespace == prefixWithName || (t.Namespace != null && t.Namespace.StartsWith(prefixWithName + ".")));
                    if (typeWithNamespace != null)
                    {
                        return(new ResolveContextNamespace(prefixWithName));
                    }
                }
            }

            // Custom resolver
            ICustomResolver        icr;
            ResolveContextConstant rcc;

            if ((context == null && (icr = _currentInstance as ICustomResolver) != null) || ((rcc = context as ResolveContextConstant) != null && (icr = rcc.Constant as ICustomResolver) != null))
            {
                return(new ResolveContextConstant(icr.Resolve(simpleNameIdentifier.Name)));
            }

            // Is it a type?
            if (context == null || context is ResolveContextNamespace || context is ResolveContextType)
            {
                IEnumerable <Type> searchTypes;
                if (context is ResolveContextType)
                {
                    searchTypes = ((ResolveContextType)context).Type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
                }
                else
                {
                    searchTypes = candidatePrefixes.SelectMany(prf => _assemblies.SelectMany(a => a.GetTypes()).Where(t => t.Namespace == prf));
                }
                foreach (var type in searchTypes.Where(t => t.Name == simpleNameIdentifier.Name))
                {
                    if (simpleNameIdentifier.GenericTypeArguments == null && !type.IsGenericType)
                    {
                        return(new ResolveContextType(type));
                    }

                    if (simpleNameIdentifier.GenericTypeArguments != null && type.IsGenericType && type.GetGenericArguments().Length == simpleNameIdentifier.GenericTypeArguments.Count)
                    {
                        return(new ResolveContextType(type.MakeGenericType(simpleNameIdentifier.GenericTypeArguments.Select(tn => ResolveType(tn)).ToArray())));
                    }
                }
            }

            Type typeInContext = context == null ? _currentType : context.ExpressionType;

            if (typeInContext != null)
            {
                var parent = context ?? (_currentInstance != null ? (ResolveContext) new ResolveContextConstant(_currentInstance) : new ResolveContextType(_currentType));
                if (simpleNameIdentifier.GenericTypeArguments == null)
                {
                    bool expectStatic = (context == null && _currentInstance == null) || (context is ResolveContextType);

                    // Is it a field or an event? (GetFields() finds the backing field of the event, which has the same name as the event)
                    foreach (var field in typeInContext.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).Where(f => f.Name == simpleNameIdentifier.Name))
                    {
                        if (field.IsStatic != expectStatic)
                        {
                            throw new InvalidOperationException("Cannot access instance field through type name or static field through instance.");
                        }
                        return(new ResolveContextExpression(Expression.Field(field.IsStatic ? null : parent.ToExpression(), field)));
                    }

                    // Is it a non-indexed property?
                    foreach (var property in typeInContext.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).Where(p => p.Name == simpleNameIdentifier.Name && p.GetIndexParameters().Length == 0))
                    {
                        bool isStatic = property.GetGetMethod() != null?property.GetGetMethod().IsStatic : property.GetSetMethod().IsStatic;

                        if (isStatic != expectStatic)
                        {
                            throw new InvalidOperationException("Cannot access instance property through type name or static property through instance.");
                        }
                        return(new ResolveContextExpression(Expression.Property(isStatic ? null : parent.ToExpression(), property)));
                    }
                }

                // Is it a method group?
                var methodList = new List <MethodGroupMember>();
                foreach (var method in typeInContext.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).Where(m => m.Name == simpleNameIdentifier.Name))
                {
                    if (simpleNameIdentifier.GenericTypeArguments == null)
                    {
                        methodList.Add(new MethodGroupMember(method, isExtensionMethod: false));
                    }
                    else if (simpleNameIdentifier.GenericTypeArguments != null && method.IsGenericMethod && method.GetGenericArguments().Length == simpleNameIdentifier.GenericTypeArguments.Count)
                    {
                        methodList.Add(new MethodGroupMember(method.MakeGenericMethod(simpleNameIdentifier.GenericTypeArguments.Select(tn => ResolveType(tn)).ToArray()), isExtensionMethod: false));
                    }
                }

                // Is it an extension method?
                foreach (var method in _assemblies.SelectMany(a => a.GetTypes()).SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Static)).Where(m => m.Name == simpleNameIdentifier.Name && m.IsDefined(typeof(ExtensionAttribute), false)))
                {
                    var prms = method.GetParameters();
                    if (prms.Length == 0)
                    {
                        continue;
                    }

                    if (simpleNameIdentifier.GenericTypeArguments == null)
                    {
                        methodList.Add(new MethodGroupMember(method, isExtensionMethod: true));
                    }
                    else if (simpleNameIdentifier.GenericTypeArguments != null && method.IsGenericMethod && method.GetGenericArguments().Length == simpleNameIdentifier.GenericTypeArguments.Count)
                    {
                        methodList.Add(new MethodGroupMember(method.MakeGenericMethod(simpleNameIdentifier.GenericTypeArguments.Select(tn => ResolveType(tn)).ToArray()), isExtensionMethod: true));
                    }
                }
                if (methodList.Count > 0)
                {
                    return(new ResolveContextMethodGroup(parent, methodList, simpleNameIdentifier.Name));
                }
            }

            throw new InvalidOperationException("The name “{0}” could not be resolved.".Fmt(simpleName));
        }