예제 #1
0
 private void LoadAssemblies(string[] assembliesToLoad, IList <Assembly> loadedAssemblies)
 {
     foreach (string assemblyName in assembliesToLoad)
     {
         // Attempt to load assembly. Failures call logger and return null.
         Assembly a = AssemblyUtilities.LoadAssembly(assemblyName, this._logger);
         if (a != null)
         {
             loadedAssemblies.Add(a);
         }
     }
 }
예제 #2
0
        /// <summary>
        /// Returns the set of <see cref="Assembly"/> instances that are referenced
        /// by the given <paramref name="assembly"/>.
        /// </summary>
        /// <remarks>
        /// The resulting collection will contain only those assemblies that loaded
        /// successfully, and it will not contain <c>null</c> values.  Failed loads
        /// will be logged to the <paramref name="logger"/>.
        /// </remarks>
        /// <param name="assembly">The <see cref="Assembly"/> whose referenced assemblies are required.</param>
        /// <param name="logger">The optional logger to use to report known load failures.</param>
        /// <returns>The collection of referenced assemblies.</returns>
        public static IEnumerable <Assembly> GetReferencedAssemblies(Assembly assembly, Action <string> logger)
        {
            System.Diagnostics.Debug.Assert(assembly != null, "assembly cannot be null");
            AssemblyName[]  assemblyNames = (assembly == null) ? Array.Empty <AssemblyName>() : assembly.GetReferencedAssemblies();
            List <Assembly> assemblies    = new List <Assembly>();

            foreach (AssemblyName assemblyName in assemblyNames)
            {
                Assembly a = AssemblyUtilities.LoadAssembly(assemblyName, logger);
                if (a != null)
                {
                    assemblies.Add(a);
                }
            }
            return(assemblies);
        }
예제 #3
0
        /// <summary>
        /// Gets the data objects for the <see cref="BusinessLogicContext"/> instances
        /// known by the current model.  These data objects are marshalled across
        /// the AppDomain boundary by <see cref="ContextViewModel"/>.
        /// </summary>
        /// <returns>The set of data objects for the <see cref="BusinessLogicContext"/>s.
        /// This collection will always contain at least one element for the
        /// default empty context.</returns>
        public IContextData[] GetContextDataItems()
        {
            // This is lazily computed and cached.
            if (this._contexts == null)
            {
                List <Assembly> loadedAssemblies = new List <Assembly>();
                this._contexts = new List <IBusinessLogicContext>();

                // First load into this AppDomain all the assemblies we have been
                // asked to load.  These 2 lists represent the assemblies of the candidate
                // types as well as all assemblies referenced by the candidate types'
                // assemblies.
                // Note, order is important here. Paths to reference assemblies were collected in the VS
                // app domain and could be static from when they were originally loaded. Assemblies
                // containing the context types were created dynamically and may be more recent. We
                // must load the assemblies containing the context types first since multiple assemblies
                // with the same name may not be loaded.
                this.LoadAssemblies(this.BusinessLogicData.AssemblyPaths, loadedAssemblies);
                this.LoadAssemblies(this.BusinessLogicData.ReferenceAssemblyPaths, loadedAssemblies);

                // Next, find the context types we were asked to use from those loaded assemblies
                List <Type>      foundTypes       = new List <Type>();
                HashSet <string> contextTypeNames = new HashSet <string>(this.BusinessLogicData.ContextTypeNames);

                // We match the type from the other AppDomain to the corresponding one in our
                // AppDomain in one of two ways:
                //  1. Type.GetType()
                //  2. Scanning Assembly.GetExportedTypes
                // We do this because Type.GetType() is faster, but it will not work
                // for assemblies that cannot be loaded by the AssemblyName alone
                // (which occurs with binary references outside the project and in
                // class library projects when ASP.NET does not use the ASP.NET
                // temporary folders).

                // Pass 1: try to get the type directly
                foreach (string typeName in this.BusinessLogicData.ContextTypeNames)
                {
                    Type t = Type.GetType(typeName, /* throwOnError */ false);
                    if (t != null)
                    {
                        foundTypes.Add(t);
                        contextTypeNames.Remove(t.AssemblyQualifiedName);
                    }
                }

                // Pass 2: for any types not loaded above, locate them manually.
                foreach (Assembly a in loadedAssemblies)
                {
                    if (contextTypeNames.Count > 0)
                    {
                        // Ask for all exported types.  Use the safe version that logs issues
                        // and unconditionally returns the collection (which could be empty).
                        Type[] types = AssemblyUtilities.GetExportedTypes(a, this._logger).ToArray();

                        foreach (Type t in types)
                        {
                            // We remove each match from the candidate list and will take an early out
                            // once that list is empty.
                            if (contextTypeNames.Count > 0 && contextTypeNames.Contains(t.AssemblyQualifiedName))
                            {
                                foundTypes.Add(t);
                                contextTypeNames.Remove(t.AssemblyQualifiedName);
                            }
                        }
                    }
                }

                // Add the default empty context at the top always
                this._contexts.Add(new BusinessLogicContext(null, Resources.BusinessLogic_Class_Empty_Class_Name));

                // Create a BusinessLogicContext object for every type we matched in the new AppDomain
                foreach (Type t in foundTypes)
                {
                    try
                    {
                        if (typeof(DataContext).IsAssignableFrom(t))
                        {
                            this._contexts.Add(new LinqToSqlContext(t));
                        }
                        else if (typeof(ObjectContext).IsAssignableFrom(t))
                        {
                            this._contexts.Add(new LinqToEntitiesContext(t));
                        }
                        else if (typeof(DbContext).IsAssignableFrom(t))
                        {
                            this._contexts.Add(new LinqToEntitiesDbContext(t));
                        }
                        else
                        {
                            this._logger(string.Format(CultureInfo.CurrentCulture, Resources.BusinessLogicClass_InvalidContextType, t.FullName));
                        }
                    }
                    catch (Exception ex)
                    {
                        this._logger(string.Format(CultureInfo.CurrentCulture, Resources.BusinessLogicClass_Failed_Load, t.FullName, ex.ToString()));
                    }
                }

                // Report every type we did not match
                foreach (string typeName in contextTypeNames)
                {
                    this._logger(string.Format(CultureInfo.CurrentCulture, Resources.BusinessLogicClass_Failed_Type_Load, typeName));
                }
            }

            // just select out all the ContextData's.  The other AppDomain does not get access
            // to the BusinessLogicContext objects, because we maintain type separation between
            // the AppDomains.
            return(this._contexts.Select <IBusinessLogicContext, IContextData>(blc => blc.ContextData).ToArray());
        }