Changeset 6174 for trunk/sources
- Timestamp:
- 05/10/11 14:28:48 (13 years ago)
- Location:
- trunk/sources/HeuristicLab.PluginInfrastructure/3.3
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.PluginInfrastructure/3.3/ApplicationManager.cs
r5445 r6174 28 28 /// </summary> 29 29 public static class ApplicationManager { 30 // the singleton instance is initialized to LightweightApplicationManager as long as no other application manager is registered 31 private static IApplicationManager appManager = new LightweightApplicationManager(); 30 // the singleton instance is initialized to LightweightApplicationManager as long as no other application manager is registered 31 private static IApplicationManager appManager; 32 32 33 /// <summary> 33 34 /// Gets the application manager singleton. 34 35 /// </summary> 35 36 public static IApplicationManager Manager { 36 get { return appManager; } 37 get { 38 if (appManager == null) 39 appManager = new LightweightApplicationManager(); 40 return appManager; 41 } 37 42 } 38 43 … … 42 47 /// <param name="manager"></param> 43 48 internal static void RegisterApplicationManager(IApplicationManager manager) { 44 if ( !(appManager is LightweightApplicationManager)) throw new InvalidOperationException("The application manager has already been set.");49 if (appManager != null && !(appManager is LightweightApplicationManager)) throw new InvalidOperationException("The application manager has already been set."); 45 50 else { 46 51 appManager = manager; -
trunk/sources/HeuristicLab.PluginInfrastructure/3.3/DefaultApplicationManager.cs
r6021 r6174 21 21 22 22 using System; 23 using System.Collections.Generic;24 using System.IO;25 using System.Linq;26 using System.Reflection;27 using HeuristicLab.PluginInfrastructure.Manager;28 23 29 24 namespace HeuristicLab.PluginInfrastructure { 30 25 31 /// <summary> 32 /// The DefaultApplicationManager provides properties to retrieve the list of available plugins and applications. 33 /// It also provides methods for type discovery and instantiation for types declared in plugins. 26 /// <summary> 34 27 /// The DefaultApplicationManager is registered as ApplicationManager.Manager singleton for each HL application 35 28 /// started via the plugin infrastructure. 36 29 /// </summary> 37 internal sealed class DefaultApplicationManager : MarshalByRefObject, IApplicationManager { 38 /// <summary> 39 /// Fired when a plugin is loaded. 40 /// </summary> 41 internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded; 42 /// <summary> 43 /// Fired when a plugin is unloaded (when the application terminates). 44 /// </summary> 45 internal event EventHandler<PluginInfrastructureEventArgs> PluginUnloaded; 46 47 // cache for the AssemblyResolveEvent 48 // which must be handled when assemblies are loaded dynamically after the application start 49 private Dictionary<string, Assembly> loadedAssemblies; 50 51 private List<IPlugin> loadedPlugins; 52 53 private List<PluginDescription> plugins; 54 /// <summary> 55 /// Gets all plugins. 56 /// </summary> 57 public IEnumerable<IPluginDescription> Plugins { 58 get { return plugins.Cast<IPluginDescription>(); } 59 } 60 61 private List<ApplicationDescription> applications; 62 /// <summary> 63 /// Gets all installed applications. 64 /// </summary> 65 public IEnumerable<IApplicationDescription> Applications { 66 get { return applications.Cast<IApplicationDescription>(); } 67 } 30 internal sealed class DefaultApplicationManager : SandboxApplicationManager { 68 31 69 32 internal DefaultApplicationManager() 70 33 : base() { 71 loadedAssemblies = new Dictionary<string, Assembly>();72 loadedPlugins = new List<IPlugin>();73 34 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { 74 35 if (loadedAssemblies.ContainsKey(args.Name)) { … … 79 40 } 80 41 81 /// <summary> 82 /// Prepares the application domain for the execution of an HL application. 83 /// Pre-loads all <paramref name="plugins"/>. 84 /// </summary> 85 /// <param name="apps">Enumerable of available HL applications.</param> 86 /// <param name="plugins">Enumerable of plugins that should be pre-loaded.</param> 87 internal void PrepareApplicationDomain(IEnumerable<ApplicationDescription> apps, IEnumerable<PluginDescription> plugins) { 88 this.plugins = new List<PluginDescription>(plugins); 89 this.applications = new List<ApplicationDescription>(apps); 90 ApplicationManager.RegisterApplicationManager(this); 91 LoadPlugins(plugins); 92 } 93 94 /// <summary> 95 /// Loads the <paramref name="plugins"/> into this application domain. 96 /// </summary> 97 /// <param name="plugins">Enumerable of plugins that should be loaded.</param> 98 private void LoadPlugins(IEnumerable<PluginDescription> plugins) { 99 // load all loadable plugins (all dependencies available) into the execution context 100 foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) { 101 foreach (string fileName in desc.AssemblyLocations) { 102 // load assembly reflection only first to get the full assembly name 103 var reflectionOnlyAssembly = Assembly.ReflectionOnlyLoadFrom(fileName); 104 // load the assembly into execution context using full assembly name 105 var asm = Assembly.Load(reflectionOnlyAssembly.FullName); 106 RegisterLoadedAssembly(asm); 107 // instantiate and load all plugins in this assembly 108 foreach (var plugin in GetInstances<IPlugin>(asm)) { 109 plugin.OnLoad(); 110 loadedPlugins.Add(plugin); 111 } 112 } 113 OnPluginLoaded(new PluginInfrastructureEventArgs(desc)); 114 desc.Load(); 115 } 116 } 117 118 /// <summary> 119 /// Runs the application declared in <paramref name="appInfo"/>. 120 /// This is a synchronous call. When the application is terminated all plugins are unloaded. 121 /// </summary> 122 /// <param name="appInfo">Description of the application to run</param> 123 internal void Run(ApplicationDescription appInfo) { 124 IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap(); 125 try { 126 runnablePlugin.Run(); 127 } 128 finally { 129 // unload plugins in reverse order 130 foreach (var plugin in loadedPlugins.Reverse<IPlugin>()) { 131 plugin.OnUnload(); 132 } 133 foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) { 134 desc.Unload(); 135 OnPluginUnloaded(new PluginInfrastructureEventArgs(desc)); 136 } 137 } 138 } 139 140 /// <summary> 141 /// Loads raw assemblies dynamically from a byte array 142 /// </summary> 143 /// <param name="assemblies">bytearray of all raw assemblies that should be loaded</param> 144 internal void LoadAssemblies(IEnumerable<byte[]> assemblies) { 145 foreach (byte[] asm in assemblies) { 146 Assembly loadedAsm = Assembly.Load(asm); 147 RegisterLoadedAssembly(loadedAsm); 148 } 149 } 150 151 // register assembly in the assembly cache for the AssemblyResolveEvent 152 private void RegisterLoadedAssembly(Assembly asm) { 153 if (loadedAssemblies.ContainsKey(asm.FullName) || loadedAssemblies.ContainsKey(asm.GetName().Name)) { 154 throw new ArgumentException("An assembly with the name " + asm.GetName().Name + " has been registered already.", "asm"); 155 } 156 loadedAssemblies.Add(asm.FullName, asm); 157 loadedAssemblies.Add(asm.GetName().Name, asm); // add short name 158 } 159 160 /// <summary> 161 /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/> 162 /// </summary> 163 /// <typeparam name="T">Most general type.</typeparam> 164 /// <returns>Enumerable of the created instances.</returns> 165 internal static IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class { 166 List<T> instances = new List<T>(); 167 foreach (Type t in GetTypes(typeof(T), plugin, true)) { 168 T instance = null; 169 try { instance = (T)Activator.CreateInstance(t); } 170 catch { } 171 if (instance != null) instances.Add(instance); 172 } 173 return instances; 174 } 175 /// <summary> 176 /// Creates an instance of all types declared in assembly <paramref name="asm"/> that are subtypes or the same type of the specified <typeparamref name="type"/>. 177 /// </summary> 178 /// <typeparam name="T">Most general type.</typeparam> 179 /// <param name="asm">Declaring assembly.</param> 180 /// <returns>Enumerable of the created instances.</returns> 181 private static IEnumerable<T> GetInstances<T>(Assembly asm) where T : class { 182 List<T> instances = new List<T>(); 183 foreach (Type t in GetTypes(typeof(T), asm, true)) { 184 T instance = null; 185 try { instance = (T)Activator.CreateInstance(t); } 186 catch { } 187 if (instance != null) instances.Add(instance); 188 } 189 return instances; 190 } 191 /// <summary> 192 /// Creates an instance of all types that are subtypes or the same type of the specified type 193 /// </summary> 194 /// <typeparam name="T">Most general type.</typeparam> 195 /// <returns>Enumerable of the created instances.</returns> 196 internal static IEnumerable<T> GetInstances<T>() where T : class { 197 return from i in GetInstances(typeof(T)) 198 select (T)i; 199 } 200 201 /// <summary> 202 /// Creates an instance of all types that are subtypes or the same type of the specified type 203 /// </summary> 204 /// <param name="type">Most general type.</param> 205 /// <returns>Enumerable of the created instances.</returns> 206 internal static IEnumerable<object> GetInstances(Type type) { 207 List<object> instances = new List<object>(); 208 foreach (Type t in GetTypes(type, true)) { 209 object instance = null; 210 try { instance = Activator.CreateInstance(t); } 211 catch { } 212 if (instance != null) instances.Add(instance); 213 } 214 return instances; 215 } 216 217 /// <summary> 218 /// Finds all types that are subtypes or equal to the specified type. 219 /// </summary> 220 /// <param name="type">Most general type for which to find matching types.</param> 221 /// <param name="onlyInstantiable">Return only types that are instantiable 222 /// (interfaces, abstract classes... are not returned)</param> 223 /// <returns>Enumerable of the discovered types.</returns> 224 internal static IEnumerable<Type> GetTypes(Type type, bool onlyInstantiable) { 225 return from asm in AppDomain.CurrentDomain.GetAssemblies() 226 from t in GetTypes(type, asm, onlyInstantiable) 227 select t; 228 } 229 230 internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool assignableToAllTypes) { 231 IEnumerable<Type> result = GetTypes(types.First(), onlyInstantiable); 232 foreach (Type type in types.Skip(1)) { 233 IEnumerable<Type> discoveredTypes = GetTypes(type, onlyInstantiable); 234 if (assignableToAllTypes) result = result.Intersect(discoveredTypes); 235 else result = result.Union(discoveredTypes); 236 } 237 return result; 238 } 239 240 /// <summary> 241 /// Finds all types that are subtypes or equal to the specified type if they are part of the given 242 /// <paramref name="pluginDescription"/>. 243 /// </summary> 244 /// <param name="type">Most general type for which to find matching types.</param> 245 /// <param name="pluginDescription">The plugin the subtypes must be part of.</param> 246 /// <param name="onlyInstantiable">Return only types that are instantiable 247 /// (interfaces, abstract classes... are not returned)</param> 248 /// <returns>Enumerable of the discovered types.</returns> 249 internal static IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription, bool onlyInstantiable) { 250 PluginDescription pluginDesc = (PluginDescription)pluginDescription; 251 return from asm in AppDomain.CurrentDomain.GetAssemblies() 252 where !IsDynamicAssembly(asm) 253 where pluginDesc.AssemblyLocations.Any(location => location.Equals(Path.GetFullPath(asm.Location), StringComparison.CurrentCultureIgnoreCase)) 254 from t in GetTypes(type, asm, onlyInstantiable) 255 select t; 256 } 257 258 internal static IEnumerable<Type> GetTypes(IEnumerable<Type> types, IPluginDescription pluginDescription, bool onlyInstantiable, bool assignableToAllTypes) { 259 IEnumerable<Type> result = GetTypes(types.First(), pluginDescription, onlyInstantiable); 260 foreach (Type type in types.Skip(1)) { 261 IEnumerable<Type> discoveredTypes = GetTypes(type, pluginDescription, onlyInstantiable); 262 if (assignableToAllTypes) result = result.Intersect(discoveredTypes); 263 else result = result.Union(discoveredTypes); 264 } 265 return result; 266 } 267 268 private static bool IsDynamicAssembly(Assembly asm) { 269 return (asm is System.Reflection.Emit.AssemblyBuilder) || string.IsNullOrEmpty(asm.Location); 270 } 271 272 /// <summary> 273 /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly. 274 /// </summary> 275 /// <param name="type">Most general type we want to find.</param> 276 /// <param name="assembly">Assembly that should be searched for types.</param> 277 /// <param name="onlyInstantiable">Return only types that are instantiable 278 /// (interfaces, abstract classes... are not returned)</param> 279 /// <returns>Enumerable of the discovered types.</returns> 280 private static IEnumerable<Type> GetTypes(Type type, Assembly assembly, bool onlyInstantiable) { 281 return from t in assembly.GetTypes() 282 where CheckTypeCompatibility(type, t) 283 where onlyInstantiable == false || 284 (!t.IsAbstract && !t.IsInterface && !t.HasElementType) 285 where !IsNonDiscoverableType(t) 286 select BuildType(t, type); 287 } 288 289 private static bool IsNonDiscoverableType(Type t) { 290 return t.GetCustomAttributes(typeof(NonDiscoverableTypeAttribute), false).Any(); 291 } 292 293 private static bool CheckTypeCompatibility(Type type, Type other) { 294 if (type.IsAssignableFrom(other)) 295 return true; 296 if (type.IsGenericType && other.IsGenericType) { 297 try { 298 if (type.IsAssignableFrom(other.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArguments()))) 299 return true; 300 } 301 catch (Exception) { } 302 } 303 return false; 304 } 305 private static Type BuildType(Type type, Type protoType) { 306 if (type.IsGenericType && protoType.IsGenericType) 307 return type.GetGenericTypeDefinition().MakeGenericType(protoType.GetGenericArguments()); 308 else 309 return type; 310 } 311 312 private void OnPluginLoaded(PluginInfrastructureEventArgs e) { 313 if (PluginLoaded != null) PluginLoaded(this, e); 314 } 315 316 private void OnPluginUnloaded(PluginInfrastructureEventArgs e) { 317 if (PluginUnloaded != null) PluginUnloaded(this, e); 318 } 319 320 // infinite lease time 42 /// infinite lease time 321 43 /// <summary> 322 44 /// Initializes the life time service with infinite lease time. … … 326 48 return null; 327 49 } 328 329 #region IApplicationManager Members330 331 IEnumerable<T> IApplicationManager.GetInstances<T>() {332 return GetInstances<T>();333 }334 335 IEnumerable<object> IApplicationManager.GetInstances(Type type) {336 return GetInstances(type);337 }338 339 IEnumerable<Type> IApplicationManager.GetTypes(Type type, bool onlyInstantiable) {340 return GetTypes(type, onlyInstantiable);341 }342 IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, bool onlyInstantiable, bool assignableToAllTypes) {343 return GetTypes(types, onlyInstantiable, assignableToAllTypes);344 }345 346 IEnumerable<Type> IApplicationManager.GetTypes(Type type, IPluginDescription plugin, bool onlyInstantiable) {347 return GetTypes(type, plugin, onlyInstantiable);348 }349 IEnumerable<Type> IApplicationManager.GetTypes(IEnumerable<Type> types, IPluginDescription plugin, bool onlyInstantiable, bool assignableToAllTypes) {350 return GetTypes(types, plugin, onlyInstantiable, assignableToAllTypes);351 }352 353 354 /// <summary>355 /// Finds the plugin that declares the <paramref name="type">type</paramref>.356 /// </summary>357 /// <param name="type">The type of interest.</param>358 /// <returns>The description of the plugin that declares the given type or null if the type has not been declared by a known plugin.</returns>359 public IPluginDescription GetDeclaringPlugin(Type type) {360 if (type == null) throw new ArgumentNullException("type");361 foreach (PluginDescription info in Plugins) {362 if (info.AssemblyLocations.Contains(Path.GetFullPath(type.Assembly.Location))) return info;363 }364 return null;365 }366 #endregion367 50 } 368 51 } -
trunk/sources/HeuristicLab.PluginInfrastructure/3.3/HeuristicLab.PluginInfrastructure-3.3.csproj
r5997 r6174 220 220 <Compile Include="BaseClasses\ApplicationBase.cs" /> 221 221 <Compile Include="BaseClasses\PluginBase.cs" /> 222 <Compile Include="SandboxApplicationManager.cs" /> 222 223 <Compile Include="DefaultApplicationManager.cs" /> 223 224 <Compile Include="ErrorHandling\ErrorDialog.cs"> -
trunk/sources/HeuristicLab.PluginInfrastructure/3.3/Sandboxing/SandboxManager.cs
r5523 r6174 21 21 22 22 using System; 23 using System.Collections.Generic;24 using System.Diagnostics;25 using System.Linq;26 23 using System.Reflection; 27 24 using System.Security; 28 25 using System.Security.Permissions; 29 using System.Security.Policy;30 26 using HeuristicLab.PluginInfrastructure.Manager; 31 27 32 28 namespace HeuristicLab.PluginInfrastructure.Sandboxing { 33 public class SandboxManager {29 public static class SandboxManager { 34 30 35 // static class 36 private SandboxManager() { } 31 /// <summary> 32 /// Creates an privileged sandbox, meaning that the executed code is fully trusted and permissions are not restricted. 33 /// This method is a fall back for trusted users in HeuristicLab Hive. 34 /// </summary> 35 public static AppDomain CreateAndInitPrivilegedSandbox(string appDomainName, string applicationBase, string configFilePath) { 36 PermissionSet pSet; 37 pSet = new PermissionSet(PermissionState.Unrestricted); 37 38 38 private static StrongName CreateStrongName(Assembly assembly) { 39 if (assembly == null) 40 throw new ArgumentNullException("assembly"); 41 42 AssemblyName assemblyName = assembly.GetName(); 43 Trace.Assert(assemblyName != null, "Could not get assembly name"); 44 45 // get the public key blob 46 byte[] publicKey = assemblyName.GetPublicKey(); 47 if (publicKey == null || publicKey.Length == 0) 48 throw new InvalidOperationException("Assembly is not strongly named"); 49 50 StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey); 51 52 // and create the StrongName 53 return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version); 54 } 55 56 #region ISandboxManager Members 57 public static AppDomain CreateAndInitSandbox(string appDomainName, string applicationBase, string configFilePath) { 58 PermissionSet pset; 59 60 #region permission set for sandbox 61 // Uncomment code for sandboxed appdomain 62 //pset = new PermissionSet(PermissionState.None); 63 //pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 64 //pset.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)); 65 //FileIOPermission fPerm = new FileIOPermission(PermissionState.None); 66 67 //foreach (IPluginDescription plugin in ApplicationManager.Manager.Plugins) { 68 // fPerm.AddPathList(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, plugin.Files.ToArray()); 69 //} 70 71 //pset.AddPermission(fPerm); 72 #endregion 73 74 #region permission set of unrestricted appdomain 75 // unrestricted appdomain 76 pset = new PermissionSet(PermissionState.Unrestricted); 77 #endregion 78 79 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation; 39 AppDomainSetup setup = new AppDomainSetup(); 80 40 setup.PrivateBinPath = applicationBase; 81 41 setup.ApplicationBase = applicationBase; 82 42 setup.ConfigurationFile = configFilePath; 83 43 84 AppDomain applicationDomain = AppDomain.CreateDomain(appDomainName, AppDomain.CurrentDomain.Evidence, setup, pset, CreateStrongName(Assembly.GetExecutingAssembly()));85 44 Type applicationManagerType = typeof(DefaultApplicationManager); 86 DefaultApplicationManager applicationManager = 87 (DefaultApplicationManager)applicationDomain.CreateInstanceAndUnwrap(applicationManagerType.Assembly.FullName, applicationManagerType.FullName, true, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null, null); 45 AppDomain applicationDomain = AppDomain.CreateDomain(appDomainName, null, setup, pSet, null); 46 DefaultApplicationManager applicationManager = (DefaultApplicationManager)applicationDomain.CreateInstanceAndUnwrap(applicationManagerType.Assembly.FullName, applicationManagerType.FullName, true, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null, null); 47 88 48 PluginManager pm = new PluginManager(applicationBase); 89 49 pm.DiscoverAndCheckPlugins(); 90 ApplicationDescription[] apps = pm.Applications.Cast<ApplicationDescription>().ToArray(); 91 PluginDescription[] plugins = pm.Plugins.Cast<PluginDescription>().ToArray(); 92 applicationManager.PrepareApplicationDomain(apps, plugins); 50 applicationManager.PrepareApplicationDomain(pm.Applications, pm.Plugins); 51 93 52 return applicationDomain; 94 53 } 95 #endregion 54 55 /// <summary> 56 /// Creates a sandbox with restricted permissions. 57 /// Code that is executed in such an AppDomain is partially-trusted and is not allowed to call or override 58 /// methods that require full trust. 59 /// </summary> 60 public static AppDomain CreateAndInitSandbox(string appDomainName, string applicationBase, string configFilePath) { 61 PermissionSet pSet; 62 63 pSet = new PermissionSet(PermissionState.None); 64 pSet.AddPermission(new SecurityPermission(PermissionState.None)); 65 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 66 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Infrastructure)); 67 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); 68 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter)); 69 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.ControlAppDomain)); 70 //needed for HeuristicLab.Persistence, see DynamicMethod Constructor (String, Type, array<Type []()>[], Type, Boolean) 71 pSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.ControlEvidence)); 72 73 ReflectionPermission refPerm = new ReflectionPermission(PermissionState.Unrestricted); 74 pSet.AddPermission(refPerm); 75 76 FileIOPermission ioPerm = new FileIOPermission(PermissionState.None); 77 //allow path discovery for system drive, needed by HeuristicLab.Persistence: Serializer.BuildTypeCache() -> Assembly.CodeBase 78 ioPerm.AddPathList(FileIOPermissionAccess.PathDiscovery, Environment.SystemDirectory.Substring(0, 3)); 79 //allow full access to the appdomain's base directory 80 ioPerm.AddPathList(FileIOPermissionAccess.AllAccess, applicationBase); 81 pSet.AddPermission(ioPerm); 82 83 AppDomainSetup setup = new AppDomainSetup(); 84 setup.PrivateBinPath = applicationBase; 85 setup.ApplicationBase = applicationBase; 86 setup.ConfigurationFile = configFilePath; 87 88 Type applicationManagerType = typeof(SandboxApplicationManager); 89 AppDomain applicationDomain = AppDomain.CreateDomain(appDomainName, null, setup, pSet, null); 90 SandboxApplicationManager applicationManager = (SandboxApplicationManager)applicationDomain.CreateInstanceAndUnwrap(applicationManagerType.Assembly.FullName, applicationManagerType.FullName, true, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null, null); 91 92 PluginManager pm = new PluginManager(applicationBase); 93 pm.DiscoverAndCheckPlugins(); 94 applicationManager.PrepareApplicationDomain(pm.Applications, pm.Plugins); 95 96 return applicationDomain; 97 } 96 98 } 97 99 }
Note: See TracChangeset
for help on using the changeset viewer.