Changeset 2295 for branches/eraser6/pluginsRewrite
- Timestamp:
- 1/4/2011 7:05:39 AM (2 years ago)
- Location:
- branches/eraser6/pluginsRewrite/Eraser.Plugins
- Files:
-
- 2 edited
-
Host.cs (modified) (9 diffs)
-
PluginInfo.cs (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eraser6/pluginsRewrite/Eraser.Plugins/Host.cs
r2292 r2295 90 90 /// </summary> 91 91 /// <remarks>The returned list is read-only</remarks> 92 public abstract IList<PluginIn stance> Plugins92 public abstract IList<PluginInfo> Plugins 93 93 { 94 94 get; … … 149 149 { 150 150 //Load all core plugins first 151 foreach (KeyValuePair<string, string> plugin in CorePlugins) 152 { 153 LoadCorePlugin(Path.Combine(PluginsFolder, plugin.Key), plugin.Value); 151 foreach (string name in CorePlugins) 152 { 153 if (!LoadPlugin(new AssemblyName(name))) 154 throw new FileLoadException(S._("The required Core plugin {0} could not be " + 155 "loaded. Repair the Eraser installation and try again.")); 154 156 } 155 157 … … 181 183 //Unload all the plugins. This will cause all the plugins to execute 182 184 //the cleanup code. 183 foreach (PluginIn stanceplugin in plugins)185 foreach (PluginInfo plugin in plugins) 184 186 if (plugin.Plugin != null) 185 187 plugin.Plugin.Dispose(); … … 189 191 } 190 192 191 public override IList<PluginIn stance> Plugins193 public override IList<PluginInfo> Plugins 192 194 { 193 195 get { return plugins.AsReadOnly(); } … … 205 207 type => type.GetInterface("Eraser.Plugins.IPlugin", true) != null); 206 208 207 //If the typePlugin type is empty the assembly doesn't implement IPlugin it's not208 // a plugin.209 //If the typePlugin type is empty, the assembly doesn't implement IPlugin and thus 210 //it is not a plugin. 209 211 return typePlugin != null; 210 212 } 211 213 212 /// <summary> 213 /// Loads the assembly at the specified path, and verifying its assembly name, 214 /// ensuring that the assembly contains a core plugin. 215 /// </summary> 216 /// <param name="filePath">The path to the assembly.</param> 217 /// <param name="assemblyName">The name of the assembly.</param> 218 private void LoadCorePlugin(string filePath, string assemblyName) 219 { 220 Assembly assembly = Assembly.ReflectionOnlyLoadFrom(filePath); 221 if (assembly.GetName().FullName.Substring(0, assemblyName.Length + 1) != 222 assemblyName + ",") 223 { 224 throw new FileLoadException(S._("The Core plugin assembly is not one which" + 225 "Eraser expects.\n\nCheck that the Eraser installation is not corrupt, or " + 226 "reinstall the program.")); 227 } 228 229 //Create the PluginInstance structure 230 PluginInstance instance = new PluginInstance(assembly, null); 214 public bool LoadPlugin(AssemblyName name) 215 { 216 //Check the plugins folder 217 foreach (string fileName in Directory.GetFiles(PluginsFolder)) 218 { 219 FileInfo file = new FileInfo(fileName); 220 if (file.Extension.Equals(".dll")) 221 try 222 { 223 Assembly assembly = Assembly.ReflectionOnlyLoadFrom(file.FullName); 224 if (AssemblyMatchesName(assembly, name)) 225 { 226 return LoadPlugin(assembly); 227 } 228 } 229 catch (BadImageFormatException) 230 { 231 } 232 catch (FileLoadException) 233 { 234 } 235 } 236 237 return false; 238 } 239 240 public override bool LoadPlugin(string filePath) 241 { 242 return LoadPlugin(Assembly.ReflectionOnlyLoadFrom(filePath)); 243 } 244 245 /// <summary> 246 /// Checks the provided assembly for its name and attempts to load it using the 247 /// plugin loading rules. 248 /// </summary> 249 /// <param name="assembly">The plugin to load. This assembly can be loaded 250 /// in the reflection-only context for security.</param> 251 /// <returns>True if the assembly was a plugin and loaded without error.</returns> 252 private bool LoadPlugin(Assembly assembly) 253 { 254 PluginInfo instance = new PluginInfo(assembly, null); 255 256 //Check that the plugin hasn't yet been loaded. 257 if (Plugins.Count( 258 plugin => plugin.Assembly.GetName().FullName == 259 assembly.GetName().FullName) > 0) 260 { 261 return true; 262 } 231 263 232 264 //Ignore non-plugins 233 265 if (!IsPlugin(instance.Assembly)) 234 throw new FileLoadException(S._("The provided Core plugin assembly is not a " + 235 "plugin.\n\nCheck that the Eraser installation is not corrupt, or reinstall " + 236 "the program.")); 266 return false; 237 267 238 268 //OK this assembly is a plugin … … 240 270 plugins.Add(instance); 241 271 272 //Load the plugin, depending on type 273 bool result = instance.LoadingPolicy == LoadingPolicy.Core ? 274 LoadCorePlugin(instance) : LoadNonCorePlugin(instance); 275 if (result) 276 { 277 //And broadcast the plugin load event 278 OnPluginLoaded(this, new PluginLoadedEventArgs(instance)); 279 } 280 281 return result; 282 } 283 284 /// <summary> 285 /// Verifies the assembly name and strong name of a plugin, ensuring that the assembly 286 /// contains a core plugin before loading and initialising it. 287 /// </summary> 288 /// <param name="info">The plugin to load.</param> 289 /// <returns>True if the plugin was loaded.</returns> 290 private bool LoadCorePlugin(PluginInfo info) 291 { 292 //Check that this plugin's name appears in our list of core plugins, otherwise this 293 //is a phony 294 if (CorePlugins.Count(x => x == info.Assembly.GetName().Name) == 0) 295 return LoadNonCorePlugin(info); 296 242 297 //Check for the presence of a valid signature: Core plugins must have the same 243 298 //public key as the current assembly 244 if (! assembly.GetName().GetPublicKey().SequenceEqual(299 if (!info.Assembly.GetName().GetPublicKey().SequenceEqual( 245 300 Assembly.GetExecutingAssembly().GetName().GetPublicKey())) 246 301 { … … 250 305 } 251 306 252 //Okay, everything's fine, initialise the plugin 253 instance.Assembly = Assembly.Load(instance.Assembly.GetName()); 254 instance.LoadingPolicy = LoadingPolicy.Core; 255 InitialisePlugin(instance); 256 } 257 258 public override bool LoadPlugin(string filePath) 259 { 260 //Create the PluginInstance structure 261 Assembly reflectAssembly = Assembly.ReflectionOnlyLoadFrom(filePath); 262 PluginInstance instance = new PluginInstance(reflectAssembly, null); 263 264 //Check that the plugin hasn't yet been loaded. 265 if (Plugins.Count( 266 plugin => plugin.Assembly.GetName().FullName == 267 reflectAssembly.GetName().FullName) > 0) 268 { 269 return true; 270 } 271 272 //Ignore non-plugins 273 if (!IsPlugin(instance.Assembly)) 274 return false; 275 276 //OK this assembly is a plugin 277 lock (plugins) 278 plugins.Add(instance); 279 280 PluginLoadEventArgs e = new PluginLoadEventArgs(instance); 281 PluginLoad(this, e); 282 if (PluginLoad == null || e.Load) 283 { 284 InitialisePlugin(instance); 285 return true; 286 } 287 288 return false; 289 } 290 291 /// <summary> 292 /// Initialises the given plugin from the plugin's description. 293 /// </summary> 294 /// <param name="instance">The <see cref="PluginInstance"/> structure to fill.</param> 295 /// <exception cref="System.IO.FileLoadException" /> 296 private void InitialisePlugin(PluginInstance instance) 297 { 298 try 299 { 300 //Iterate over every exported type, checking for the IPlugin implementation 301 Type typePlugin = instance.Assembly.GetExportedTypes().First( 302 type => type.GetInterface("Eraser.Manager.Plugin.IPlugin", true) != null); 303 if (typePlugin == null) 304 return; 305 306 //Initialize the plugin 307 instance.Plugin = (IPlugin)Activator.CreateInstance( 308 instance.Assembly.GetType(typePlugin.ToString())); 309 instance.Plugin.Initialize(this); 310 311 //And broadcast the plugin load event 312 OnPluginLoaded(this, new PluginLoadedEventArgs(instance)); 313 } 314 catch (System.Security.SecurityException e) 315 { 316 throw new FileLoadException(S._("Could not load the plugin."), 317 instance.Assembly.Location, e); 318 } 307 //Load the plugin. 308 info.Load(this); 309 return true; 310 } 311 312 /// <summary> 313 /// Queries the Plugin Host's owner on whether to load the current plugin. 314 /// </summary> 315 /// <param name="info">The plugin to load.</param> 316 /// <returns>True if the plugin was loaded.</returns> 317 private bool LoadNonCorePlugin(PluginInfo info) 318 { 319 PluginLoadEventArgs e = new PluginLoadEventArgs(info); 320 if (PluginLoad != null) 321 PluginLoad(this, e); 322 323 if (e.Load) 324 info.Load(this); 325 326 return e.Load; 327 } 328 329 private static bool AssemblyMatchesName(Assembly assembly, AssemblyName name) 330 { 331 AssemblyName assemblyName = assembly.GetName(); 332 return (name.Name == assemblyName.Name && 333 (name.Version == null || name.Version == assemblyName.Version) && 334 (name.ProcessorArchitecture == ProcessorArchitecture.None || name.ProcessorArchitecture == assemblyName.ProcessorArchitecture) && 335 (name.GetPublicKey() == null || name.GetPublicKey().SequenceEqual(assemblyName.GetPublicKey())) 336 ); 319 337 } 320 338 321 339 private Assembly AssemblyResolve(object sender, ResolveEventArgs args) 322 340 { 341 //Parse the assembly name 342 AssemblyName name = new AssemblyName(args.Name); 343 323 344 //Check the plugins folder 324 345 foreach (string fileName in Directory.GetFiles(PluginsFolder)) … … 329 350 { 330 351 Assembly assembly = Assembly.ReflectionOnlyLoadFrom(file.FullName); 331 if (assembly.GetName().FullName == args.Name) 352 if (AssemblyMatchesName(assembly, name)) 353 { 332 354 return Assembly.LoadFile(file.FullName); 355 } 333 356 } 334 357 catch (BadImageFormatException) … … 357 380 358 381 /// <summary> 359 /// The list of plugins which are core, the key is the file name, the value 360 /// is the assembly name. 361 /// </summary> 362 private readonly KeyValuePair<string, string>[] CorePlugins = 363 new KeyValuePair<string, string>[] 364 { 365 new KeyValuePair<string, string>( 366 "Eraser.DefaultPlugins.dll", 367 "Eraser.DefaultPlugins" 368 ) 369 }; 382 /// The list of plugins which are core. This list contains the names of every 383 /// assembly which are expected to be core plugins. 384 /// </summary> 385 private readonly string[] CorePlugins = new string[] { 386 "Eraser.DefaultPlugins" 387 }; 370 388 371 389 /// <summary> 372 390 /// Stores the list of plugins found within the Plugins folder. 373 391 /// </summary> 374 private List<PluginIn stance> plugins = new List<PluginInstance>();392 private List<PluginInfo> plugins = new List<PluginInfo>(); 375 393 } 376 394 } -
branches/eraser6/pluginsRewrite/Eraser.Plugins/PluginInfo.cs
r2293 r2295 67 67 internal void Load(Host host) 68 68 { 69 Assembly = Assembly.Load(Assembly.GetName()); 69 if (Assembly.ReflectionOnly) 70 Assembly = Assembly.Load(Assembly.GetName()); 70 71 71 72 try … … 73 74 //Iterate over every exported type, checking for the IPlugin implementation 74 75 Type typePlugin = Assembly.GetExportedTypes().First( 75 type => type.GetInterface("Eraser.Manager.Plugin.IPlugin", true) != null); 76 if (typePlugin == null) 77 throw new FileLoadException(S._("Could not load the plugin."), 78 Assembly.Location); 76 type => type.GetInterface("Eraser.Plugins.IPlugin", true) != null); 79 77 80 78 //Initialize the plugin 81 Plugin = (IPlugin)Activator.CreateInstance( Assembly.GetType(typePlugin.ToString()));79 Plugin = (IPlugin)Activator.CreateInstance(typePlugin); 82 80 Plugin.Initialize(host); 81 } 82 catch (InvalidOperationException e) 83 { 84 throw new FileLoadException(S._("Could not load the plugin."), 85 Assembly.Location, e); 83 86 } 84 87 catch (System.Security.SecurityException e)
Note: See TracChangeset
for help on using the changeset viewer.
