private static List<object> BuildDeclarationChain(Type callingType)
{
// We need to build the parent chain of the calling type. Since we only
// have the type itself, first we need to build the chain up from the
// type down to the root namespace, then we need to ensure that
// the chain exists in our symbol table by searching from the root namespace
// back down to the calling type. Also note that if we have a method type
// parameter, then we'll also add the MethodBase to the chain.
//
// Note that we'll populate this list in a hybrid way - we'll add the
// types for the type part of the chain, and we'll just add the string names
// of the namespaces.
// Strip off the ref-ness.
if (callingType.IsByRef)
{
callingType = callingType.GetElementType();
}
List<object> callChain = new List<object>();
for (Type t = callingType; t != null; t = t.DeclaringType)
{
callChain.Add(t);
if (t.IsGenericParameter && t.GetTypeInfo().DeclaringMethod != null)
{
MethodBase methodBase = t.GetTypeInfo().DeclaringMethod;
ParameterInfo[] parameters = methodBase.GetParameters();
bool bAdded = false;
#if UNSUPPORTEDAPI
foreach (MethodInfo methinfo in Enumerable.Where(t.DeclaringType.GetRuntimeMethods(), m => m.MetadataToken == methodBase.MetadataToken))
#else
foreach (MethodInfo methinfo in Enumerable.Where(t.DeclaringType.GetRuntimeMethods(), m => m.HasSameMetadataDefinitionAs(methodBase)))
#endif
{
if (!methinfo.IsGenericMethod)
{
continue;
}
Debug.Assert(!bAdded);
callChain.Add(methinfo);
bAdded = true;
}
Debug.Assert(bAdded);
}
}
callChain.Reverse();
// Now take out the namespaces and add them to the end of the chain.
if (callingType.Namespace != null)
{
string[] namespaces = callingType.Namespace.Split('.');
int index = 0;
foreach (string s in namespaces)
{
callChain.Insert(index++, s);
}
}
return callChain;
}