private bool NeedSeparateAppDomain()

in src/Tasks/GenerateResource.cs [1615:1850]


        private bool NeedSeparateAppDomain()
        {
            if (NeverLockTypeAssemblies)
            {
                Log.LogMessageFromResources(MessageImportance.Low, "GenerateResource.SeparateAppDomainBecauseNeverLockTypeAssembliesTrue");
                return true;
            }

            foreach (ITaskItem source in _sources)
            {
                string extension = Path.GetExtension(source.ItemSpec);

                if (String.Compare(extension, ".resources.dll", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(extension, ".dll", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(extension, ".exe", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return true;
                }

                if (String.Compare(extension, ".resx", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(extension, ".resw", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    XmlReader reader = null;
                    string name = null;

                    try
                    {
                        XmlReaderSettings readerSettings = new XmlReaderSettings();
                        readerSettings.DtdProcessing = DtdProcessing.Ignore;
                        reader = XmlReader.Create(source.ItemSpec, readerSettings);

                        while (reader.Read())
                        {
                            // Look for the <data> section
                            if (reader.NodeType == XmlNodeType.Element)
                            {
                                if (String.Equals(reader.Name, "data", StringComparison.OrdinalIgnoreCase))
                                {
                                    // Is there an attribute called type?
                                    string typeName = reader.GetAttribute("type");
                                    name = reader.GetAttribute("name");

                                    if (typeName != null)
                                    {
                                        Type type;

                                        // It is likely that we've seen this type before
                                        // we'll try our table of previously seen types
                                        // since it is *much* faster to do that than
                                        // call Type.GetType needlessly!
                                        if (!_typeTable.TryGetValue(typeName, out type))
                                        {
                                            string resolvedTypeName = typeName;

                                            // This type name might be an alias, so first resolve that if any.  
                                            int indexOfSeperator = typeName.IndexOf(",", StringComparison.Ordinal);

                                            if (indexOfSeperator != -1)
                                            {
                                                string typeFromTypeName = typeName.Substring(0, indexOfSeperator);
                                                string maybeAliasFromTypeName = typeName.Substring(indexOfSeperator + 1);

                                                if (!String.IsNullOrWhiteSpace(maybeAliasFromTypeName))
                                                {
                                                    maybeAliasFromTypeName = maybeAliasFromTypeName.Trim();

                                                    string fullName = null;
                                                    if (_aliases.TryGetValue(maybeAliasFromTypeName, out fullName))
                                                    {
                                                        resolvedTypeName = typeFromTypeName + ", " + fullName;
                                                    }
                                                }
                                            }

                                            // Can this type be found in the GAC?
                                            type = Type.GetType(resolvedTypeName, throwOnError: false, ignoreCase: false);

                                            // Remember our resolved type
                                            _typeTable[typeName] = type;
                                        }

                                        if (type == null)
                                        {
                                            // If the type could not be found in the GAC, then we're going to need
                                            // to load the referenced assemblies (those passed in through the
                                            // "References" parameter during the building of this .RESX.  Therefore,
                                            // we should create a separate app-domain, so that those assemblies
                                            // can be unlocked when the task is finished.
                                            // The type didn't start with "System." so return true.
                                            Log.LogMessageFromResources
                                            (
                                                MessageImportance.Low,
                                                "GenerateResource.SeparateAppDomainBecauseOfType",
                                                (name == null) ? String.Empty : name,
                                                typeName,
                                                source.ItemSpec,
                                                ((IXmlLineInfo)reader).LineNumber
                                            );

                                            return true;
                                        }

                                        // If there's a type, we don't need to look at any mimetype
                                        continue;
                                    }

                                    // DDB #9825.
                                    // There's no type attribute on this <data> -- if there's a MimeType, it's a serialized
                                    // object of unknown type, and we have to assume it will need a new app domain.
                                    // The possible mimetypes ResXResourceReader understands are:
                                    //  
                                    // application/x-microsoft.net.object.binary.base64
                                    // application/x-microsoft.net.object.bytearray.base64
                                    // application/x-microsoft.net.object.binary.base64
                                    // application/x-microsoft.net.object.soap.base64
                                    // text/microsoft-urt/binary-serialized/base64
                                    // text/microsoft-urt/psuedoml-serialized/base64
                                    // text/microsoft-urt/soap-serialized/base64
                                    //
                                    // Of these, application/x-microsoft.net.object.bytearray.base64 usually has a type attribute
                                    // as well; ResxResourceReader will use that Type, which may not need a new app domain. So
                                    // if there's a type attribute, we don't look at mimetype.
                                    //
                                    // If there is a mimetype and no type, we can't tell the type without deserializing and loading it, 
                                    // so we assume a new appdomain is needed.
                                    //
                                    // Actually, if application/x-microsoft.net.object.bytearray.base64 doesn't have a Type attribute, 
                                    // ResxResourceReader assumes System.String, but for safety we don't assume that here.

                                    string mimeType = reader.GetAttribute("mimetype");

                                    if (mimeType != null)
                                    {
                                        if (NeedSeparateAppDomainBasedOnSerializedType(reader))
                                        {
                                            Log.LogMessageFromResources
                                            (
                                                MessageImportance.Low,
                                                "GenerateResource.SeparateAppDomainBecauseOfMimeType",
                                                (name == null) ? String.Empty : name,
                                                mimeType,
                                                source.ItemSpec,
                                                ((IXmlLineInfo)reader).LineNumber
                                            );

                                            return true;
                                        }
                                    }
                                }
                                else if (String.Equals(reader.Name, "assembly", StringComparison.OrdinalIgnoreCase))
                                {
                                    string alias = reader.GetAttribute("alias");
                                    string fullName = reader.GetAttribute("name");

                                    if (!String.IsNullOrWhiteSpace(alias) && !String.IsNullOrWhiteSpace(fullName))
                                    {
                                        alias = alias.Trim();
                                        fullName = fullName.Trim();

                                        _aliases[alias] = fullName;
                                    }
                                }
                            }
                        }
                    }
                    catch (XmlException e)
                    {
                        Log.LogMessageFromResources
                                    (
                                        MessageImportance.Low,
                                        "GenerateResource.SeparateAppDomainBecauseOfExceptionLineNumber",
                                        source.ItemSpec,
                                        ((IXmlLineInfo)reader).LineNumber,
                                        e.Message
                                    );

                        return true;
                    }
#if FEATURE_BINARY_SERIALIZATION
                    catch (SerializationException e)
                    {
                        Log.LogMessageFromResources
                                    (
                                        MessageImportance.Low,
                                        "GenerateResource.SeparateAppDomainBecauseOfErrorDeserializingLineNumber",
                                        source.ItemSpec,
                                        (name == null) ? String.Empty : name,
                                        ((IXmlLineInfo)reader).LineNumber,
                                        e.Message
                                    );

                        return true;
                    }
#endif
                    catch (Exception e)
                    {
                        // DDB#9819
                        // Customers have reported the following exceptions coming out of this method's call to GetType():
                        //      System.Runtime.InteropServices.COMException (0x8000000A): The data necessary to complete this operation is not yet available. (Exception from HRESULT: 0x8000000A)
                        //      System.NullReferenceException: Object reference not set to an instance of an object.
                        //      System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
                        // We don't have reproes, but probably the right thing to do is to assume a new app domain is needed on almost any exception.
                        // Any problem loading the type will get logged later when the resource reader tries it.
                        //
                        // XmlException or an IO exception is also possible from an invalid input file.
                        if (ExceptionHandling.IsCriticalException(e))
                            throw;

                        // If there was any problem parsing the .resx then log a message and 
                        // fall back to using a separate AppDomain. 
                        Log.LogMessageFromResources
                                    (
                                        MessageImportance.Low,
                                        "GenerateResource.SeparateAppDomainBecauseOfException",
                                        source.ItemSpec,
                                        e.Message
                                    );

                        // In case we need more information from the customer (given this has been heavily reported
                        // and we don't understand it properly) let the usual debug switch dump the stack.
                        if (Environment.GetEnvironmentVariable("MSBUILDDEBUG") == "1")
                        {
                            Log.LogErrorFromException(e, /* stack */ true, /* inner exceptions */ true, null);
                        }

                        return true;
                    }
                    finally
                    {
                        reader?.Close();
                    }
                }
            }

            return false;
        }