Microsoft.CSharp.RuntimeBinder.SymbolTable.LoadSymbolsFromType C# (CSharp) 메소드

LoadSymbolsFromType() 개인적인 메소드

private LoadSymbolsFromType ( Type originalType ) : CType
originalType System.Type
리턴 Microsoft.CSharp.RuntimeBinder.Semantics.CType
        private CType LoadSymbolsFromType(Type originalType)
        {
            List<object> declarationChain = BuildDeclarationChain(originalType);

            Type type = originalType;
            CType ret = null;
            bool bIsByRef = type.IsByRef;
            if (bIsByRef)
            {
                type = type.GetElementType();
            }

            NamespaceOrAggregateSymbol current = _rootNamespace;

            // Go through the declaration chain and add namespaces and types for 
            // each element in the chain.
            for (int i = 0; i < declarationChain.Count; i++)
            {
                object o = declarationChain[i];
                NamespaceOrAggregateSymbol next;
                if (o is Type)
                {
                    Type t = o as Type;
                    Name name = null;
                    name = GetName(t);
                    next = _symbolTable.LookupSym(name, current, symbmask_t.MASK_AggregateSymbol).AsAggregateSymbol();

                    // Make sure we match arity as well when we find an aggregate.
                    if (next != null)
                    {
                        next = FindSymWithMatchingArity(next as AggregateSymbol, t);
                    }

                    // In the event that two different types exist that have the same name, they
                    // cannot both have entries in the symbol table with our current architecture.
                    // This can happen in dynamic, since the runtime binder lives across all
                    // call sites in an appdomain, and assemblies can have been loaded at runtime
                    // that have different types with the same name. 

                    // In the real compiler, this would have been an error and name lookup would
                    // be ambiguous, but here we never have to lookup names of types for real (only
                    // names of members).

                    // The tactical fix is this: if we encounter this situation, where we have
                    // identically named types that are not the same, then we are going to clear
                    // the entire symbol table and restart this binding. This solution is not
                    // without its own problems, since it is possible to conceive of a single
                    // dynamic binding that needs to simultaneously know about both of the 
                    // similarly named types, but we are not going to try to solve that
                    // scenario here.

                    if (next != null && next is AggregateSymbol)
                    {
                        Type existingType = (next as AggregateSymbol).AssociatedSystemType;
                        Type newType = t.GetTypeInfo().IsGenericType ? t.GetTypeInfo().GetGenericTypeDefinition() : t;

                        // We use "IsEquivalentTo" so that unified local types for NoPIA do
                        // not trigger a reset. There are other mechanisms to make those sorts
                        // of types work in some scenarios.
                        if (!existingType.IsEquivalentTo(newType))
                        {
                            throw new ResetBindException();
                        }
                    }

                    // If we haven't found this type yet, then add it to our symbol table.
                    if (next == null || t.IsNullableType())
                    {
                        // Note that if we have anything other than an AggregateSymbol, 
                        // we must be at the end of the line - that is, nothing else can
                        // have children.

                        CType ctype = ProcessSpecialTypeInChain(current, t);
                        if (ctype != null)
                        {
                            // If we had an aggregate type, its possible we're not at the end.
                            // This will happen for nullable<T> for instance.
                            if (ctype.IsAggregateType())
                            {
                                next = ctype.AsAggregateType().GetOwningAggregate();
                            }
                            else
                            {
                                ret = ctype;
                                break;
                            }
                        }
                        else
                        {
                            // This is a regular class.
                            next = AddAggregateToSymbolTable(current, t);
                        }
                    }

                    if (t == type)
                    {
                        ret = GetConstructedType(type, next.AsAggregateSymbol());
                        break;
                    }
                }
                else if (o is MethodInfo)
                {
                    // We cant be at the end.
                    Debug.Assert(i + 1 < declarationChain.Count);
                    ret = ProcessMethodTypeParameter(o as MethodInfo, declarationChain[++i] as Type, current as AggregateSymbol);
                    break;
                }
                else
                {
                    Debug.Assert(o is string);
                    next = AddNamespaceToSymbolTable(current, o as string);
                }
                current = next;
            }

            Debug.Assert(ret != null);
            if (bIsByRef)
            {
                ret = _typeManager.GetParameterModifier(ret, false);
            }
            return ret;
        }