Changeset 2475
- Timestamp:
- 11/10/09 16:52:52 (15 years ago)
- Location:
- branches/PluginInfrastructure Refactoring
- Files:
-
- 19 added
- 7 edited
- 7 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginAction.cs
r2472 r2475 25 25 using System.Diagnostics; 26 26 27 namespace HeuristicLab.PluginInfrastructure. GUI{27 namespace HeuristicLab.PluginInfrastructure.Manager { 28 28 [Flags] 29 29 enum ManagerAction { … … 57 57 58 58 public string GetInverseActionString() { 59 switch (action) {59 switch (action) { 60 60 case ManagerAction.Install: 61 61 return "Don't install"; -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginDescription.cs
r2472 r2475 25 25 using System.Xml; 26 26 27 namespace HeuristicLab.PluginInfrastructure. GUI{27 namespace HeuristicLab.PluginInfrastructure.Manager { 28 28 class PluginDescription { 29 29 private string name; -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginTag.cs
r2472 r2475 24 24 using System.Text; 25 25 26 namespace HeuristicLab.PluginInfrastructure. GUI{26 namespace HeuristicLab.PluginInfrastructure.Manager { 27 27 28 28 [Flags] 29 enum PluginState { 29 enum PluginState { 30 30 Installed = 1, 31 31 Available = 2, … … 43 43 internal PluginDescription PluginDescription { 44 44 get { return pluginDescription; } 45 set { 45 set { 46 46 pluginDescription = value; 47 47 pluginDependencies = GeneratePluginDependencies(pluginDescription); … … 135 135 return "Plugin: " + plugin.Name + "\n" + 136 136 "Version: " + plugin.Version + "\n" + 137 "Build: " + plugin.BuildDate + "\n\n" +137 "Build: " + plugin.BuildDate + "\n\n" + 138 138 (dependencies.Length != 0 ? "Requires: \n" + dependencies + "\n" : "") + 139 139 (dependents.Length != 0 ? "Used by:\n" + dependents + "\n" : "") + … … 149 149 return "plugin: " + plugin.Name + "\n" + 150 150 "Version: " + plugin.Version + "\n" + 151 "Build: " +plugin.BuildDate +"\n" +151 "Build: " + plugin.BuildDate + "\n" + 152 152 "Installed from: " + plugin.Source + "\n" + 153 153 "Requires: \n" + dependencies; … … 156 156 private string GenerateUpgradeDetails(PluginDescription upgrade) { 157 157 string dependencies = ""; 158 foreach (string dependency in upgrade.Dependencies) {158 foreach (string dependency in upgrade.Dependencies) { 159 159 dependencies += dependency + "\n"; 160 160 } 161 161 return "plugin: " + upgrade.Name + "\n" + 162 "Current version: " + plugin.Version + " (" +plugin.BuildDate+") will be upgraded to new version: " + upgrade.Version + " ("+upgrade.BuildDate+")\n"+162 "Current version: " + plugin.Version + " (" + plugin.BuildDate + ") will be upgraded to new version: " + upgrade.Version + " (" + upgrade.BuildDate + ")\n" + 163 163 "Upgraded from: " + upgrade.Source + "\n" + 164 164 "Requires: \n" + dependencies; … … 183 183 internal List<PluginTag> GetDependentTags() { 184 184 List<PluginTag> dependentTags = new List<PluginTag>(); 185 foreach (PluginTag tag in allTags) {185 foreach (PluginTag tag in allTags) { 186 186 if (tag.pluginDependencies.Contains(pluginName)) { 187 187 if (!dependentTags.Contains(tag)) { … … 201 201 internal List<PluginTag> GetDependencyTags() { 202 202 List<PluginTag> dependencyTags = new List<PluginTag>(); 203 foreach (PluginTag tag in allTags) {203 foreach (PluginTag tag in allTags) { 204 204 if (pluginDependencies.Contains(tag.pluginName)) { 205 205 if (!dependencyTags.Contains(tag)) { … … 228 228 229 229 public override int GetHashCode() { 230 if (pluginVersion != null) {230 if (pluginVersion != null) { 231 231 return pluginName.GetHashCode() + pluginVersion.GetHashCode(); 232 232 } else return pluginName.GetHashCode(); -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Attributes/AssemblyBuildDateAttribute.cs
r2472 r2475 27 27 namespace HeuristicLab.PluginInfrastructure { 28 28 /// <summary> 29 /// Attribute of an assembly when it was built.29 /// Build date attribute. Allows to declare the build date of assemblies. 30 30 /// </summary> 31 31 [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] … … 33 33 private DateTime buildDate; 34 34 /// <summary> 35 /// Gets or sets the date when the assembly has been built.35 /// Gets or sets the build date. 36 36 /// </summary> 37 37 public DateTime BuildDate { -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Attributes/PluginDependencyAttribute.cs
r2472 r2475 26 26 namespace HeuristicLab.PluginInfrastructure { 27 27 /// <summary> 28 /// This attribute can be used to specify that an assembly depends on a differentplugin.28 /// This attribute can be used to declare that an plugin depends on a another plugin. 29 29 /// </summary> 30 [AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]31 public sealed class DependencyAttribute : System.Attribute {30 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 31 public sealed class PluginDependencyAttribute : System.Attribute { 32 32 private string dependency; 33 33 34 34 /// <summary> 35 /// Gets or sets the name of the plugin that is needed to load the assembly.35 /// Gets or sets the name of the plugin that is needed to load a plugin. 36 36 /// </summary> 37 37 public string Dependency { … … 41 41 42 42 /// <summary> 43 /// Initializes a new instance of <see cref="DependencyAttribute"/>. 43 /// Initializes a new instance of <see cref="PluginDependencyAttribute"/>. 44 /// <param name="dependency">The name of the plugin that is needed to load a plugin.</param> 44 45 /// </summary> 45 public DependencyAttribute() { 46 public PluginDependencyAttribute(string dependency) { 47 this.dependency = dependency; 46 48 } 47 49 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Attributes/PluginDescriptionAttribute.cs
r2472 r2475 26 26 namespace HeuristicLab.PluginInfrastructure { 27 27 /// <summary> 28 /// This attribute can be used to specify meta data for classes.29 /// For example to specify name, version and description of applications orplugins.28 /// This attribute can be used to specify meta data for plugins. 29 /// For example to specify name, version and description of plugins. 30 30 /// </summary> 31 31 [AttributeUsage(AttributeTargets.Class)] 32 public class ClassInfoAttribute : System.Attribute {32 public class PluginDescriptionAttribute : System.Attribute { 33 33 private string name; 34 34 /// <summary> 35 /// Gets or sets the name of the plugin to which the assembly belongs to.35 /// Gets or sets the name of the plugin. 36 36 /// </summary> 37 37 public string Name { … … 58 58 } 59 59 60 private bool autoRestart;61 60 /// <summary> 62 /// Gets or sets the boolean flag whether the plugin should be automatically restarted. 61 /// Initializes a new instance of <see cref="PluginDescriptionAttribute"/>. 62 /// <param name="name">Name of the plugin</param> 63 63 /// </summary> 64 public bool AutoRestart { 65 get { return autoRestart; } 66 set { autoRestart = value; } 64 public PluginDescriptionAttribute(string name) 65 : this(name, "") { 67 66 } 68 67 69 68 /// <summary> 70 /// Initializes a new instance of <see cref="ClassInfoAttribute"/>. 69 /// Initializes a new instance of <see cref="PluginDescriptionAttribute"/>. 70 /// <param name="name">Name of the plugin</param> 71 /// <param name="description">Description of the plugin</param> 71 72 /// </summary> 72 public ClassInfoAttribute() {} 73 public PluginDescriptionAttribute(string name, string description) 74 : this(name, description, "") { 75 } 76 77 /// <summary> 78 /// Initializes a new instance of <see cref="PluginDescriptionAttribute"/>. 79 /// <param name="name">Name of the plugin</param> 80 /// <param name="description">Description of the plugin</param> 81 /// <param name="version">Version string of the plugin</param> 82 /// </summary> 83 public PluginDescriptionAttribute(string name, string description, string version) { 84 this.name = name; 85 this.version = version; 86 this.description = description; 87 } 73 88 } 74 89 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Attributes/PluginFileAttribute.cs
r2472 r2475 36 36 37 37 /// <summary> 38 /// Attribute for plugins providing information about their corresponding files. 38 /// PluginFileAttribute can be used to declare which files make up an plugin. 39 /// Multiple files can be associated to an plugin. Each file should be associated to only one plugin. 39 40 /// </summary> 40 [AttributeUsage(AttributeTargets.Class, AllowMultiple =true)]41 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 41 42 public class PluginFileAttribute : System.Attribute { 42 43 private string filename; … … 62 63 /// <summary> 63 64 /// Initializes a new instance of <see cref="PluginFileAttribute"/>. 65 /// <param name="filename">Name of the file</param> 66 /// <param name="type">Type of the file (Assembly, Executable, Data, License)</param> 64 67 /// </summary> 65 public PluginFileAttribute() { } 68 public PluginFileAttribute(string filename, PluginFileType type) { 69 this.filename = filename; 70 this.filetype = type; 71 } 66 72 } 67 73 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/BaseClasses/ApplicationBase.cs
r1189 r2475 29 29 /// Default implementation for the IApplication interface. 30 30 /// </summary> 31 public abstract class ApplicationBase : IApplication { 32 private string name; 33 private Version version; 34 private string description; 35 private bool autoRestart; 36 31 internal abstract class ApplicationBase : IApplication { 37 32 /// <summary> 38 33 /// Initializes a new instance of <see cref="ApplicationBase"/>. 39 34 /// </summary> 40 public ApplicationBase() { 41 ReadAttributes(); 42 } 35 public ApplicationBase() { } 43 36 44 private void ReadAttributes() { 45 object[] pluginAttributes = this.GetType().GetCustomAttributes(typeof(ClassInfoAttribute), false); 37 private ApplicationDescriptionAttribute ApplicationDescriptionAttribute { 38 get { 39 object[] appDescAttributes = this.GetType().GetCustomAttributes(typeof(ApplicationDescriptionAttribute), false); 46 40 47 // exactly one attribute of the type ClassInfoAttribute must be given 48 if(pluginAttributes.Length != 1) { 49 throw new InvalidPluginException(); 50 } 51 52 // after the assertion we are sure that the array access will not fail 53 ClassInfoAttribute pluginAttribute = (ClassInfoAttribute)pluginAttributes[0]; 54 if(pluginAttribute != null) { 55 // if the plugin name is not explicitly set in the attribute then the default plugin name is the FullName of the type 56 if(pluginAttribute.Name != null) { 57 this.name = pluginAttribute.Name; 58 } else { 59 this.name = this.GetType().FullName; 41 // exactly one attribute of the type ClassInfoAttribute must be given 42 if (appDescAttributes.Length != 1) { 43 throw new InvalidPluginException("Found multiple ApplicationDescriptionAttributes on type " + this.GetType()); 60 44 } 61 45 62 // if the version is not explicitly set in the attribute then the version of the assembly is used as default 63 if(pluginAttribute.Version != null) { 64 this.version = new Version(pluginAttribute.Version); 65 } else { 66 this.version = this.GetType().Assembly.GetName().Version; 67 } 68 69 // if the description is not explicitly set in the attribute then the name of name of the application is used as default 70 if(pluginAttribute.Description != null) { 71 this.description = pluginAttribute.Description; 72 } else { 73 this.description = name; 74 } 75 76 this.autoRestart = pluginAttribute.AutoRestart; 46 return (ApplicationDescriptionAttribute)appDescAttributes[0]; 77 47 } 78 48 } 79 80 49 81 50 #region IApplication Members … … 85 54 /// </summary> 86 55 public string Name { 87 get { return name; }56 get { return ApplicationDescriptionAttribute.Name; } 88 57 } 89 58 … … 92 61 /// </summary> 93 62 public Version Version { 94 get { return version; } 63 get { 64 var appDescAttribute = ApplicationDescriptionAttribute; 65 // if the version is not explicitly set in the attribute then the version of the assembly is used as default 66 if (string.IsNullOrEmpty(appDescAttribute.Version)) { 67 return this.GetType().Assembly.GetName().Version; 68 } else { 69 return new Version(appDescAttribute.Version); 70 } 71 } 95 72 } 96 73 … … 99 76 /// </summary> 100 77 public string Description { 101 get { return description; } 78 get { 79 var appDescAttribute = ApplicationDescriptionAttribute; 80 // if the description is not explicitly set in the attribute then the name of the application is used as default 81 if (string.IsNullOrEmpty(appDescAttribute.Description)) { 82 return appDescAttribute.Name; 83 } else { 84 return appDescAttribute.Description; 85 } 86 } 102 87 } 103 88 104 89 /// <summary> 105 /// Gets the boolean flag whether the application should automatically get restarted.90 /// Gets the boolean flag whether the application should by restarted after exceptions. 106 91 /// </summary> 107 public bool AutoRestart { 108 get { return autoRestart; } 92 public bool RestartOnErrors { 93 get { 94 return ApplicationDescriptionAttribute.RestartOnErrors; 95 } 109 96 } 110 97 -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs
r1229 r2475 25 25 using System.Reflection; 26 26 using System.Diagnostics; 27 using System.Linq; 27 28 28 29 namespace HeuristicLab.PluginInfrastructure { … … 31 32 /// </summary> 32 33 public abstract class PluginBase : IPlugin { 33 private string name;34 private Version version;35 private string[] files;36 private string description;37 38 34 /// <summary> 39 35 /// Initializes a new instance of <see cref="PluginBase"/>. 40 36 /// </summary> 41 public PluginBase() { 42 ReadAttributes(); 43 } 37 public PluginBase() { } 44 38 45 private void ReadAttributes() { 46 object[] pluginAttributes = this.GetType().GetCustomAttributes(typeof(ClassInfoAttribute), false); 47 48 // exactly one attribute of the type ClassInfoAttribute must be given 49 if (pluginAttributes.Length != 1) { 50 throw new InvalidPluginException(); 51 } 52 53 // after the assertion we are sure that the array access will not fail 54 ClassInfoAttribute pluginAttribute = (ClassInfoAttribute)pluginAttributes[0]; 55 56 // if the plugin name is not explicitly set in the attribute then the default plugin name is the FullName of the type 57 if (pluginAttribute != null && pluginAttribute.Name != null) { 58 this.name = pluginAttribute.Name; 59 } else { 60 this.name = this.GetType().FullName; 61 } 62 63 // if the version is not explicitly set in the attribute then the version of the assembly is used as default 64 if (pluginAttribute != null && pluginAttribute.Version != null) { 65 this.version = new Version(pluginAttribute.Version); 66 } else { 67 this.version = this.GetType().Assembly.GetName().Version; 68 } 69 70 // if the description is not explicitly set in the attribute then the name of name of the plugin is used as default 71 if (pluginAttribute != null && pluginAttribute.Description != null) { 72 this.description = pluginAttribute.Description; 73 } else { 74 this.description = name; 75 } 76 77 // get all attributes of type PluginFileAttribute, multiple usage is possible 78 PluginFileAttribute[] fileAttributes = (PluginFileAttribute[])this.GetType().GetCustomAttributes(typeof(PluginFileAttribute), false); 79 80 // exctract the file names from the attributes 81 this.files = new string[fileAttributes.Length]; 82 int i = 0; 83 foreach (PluginFileAttribute fileAttr in fileAttributes) { 84 files[i++] = fileAttr.Filename; 39 private PluginDescriptionAttribute PluginDescriptionAttribute { 40 get { 41 object[] pluginAttributes = this.GetType().GetCustomAttributes(typeof(PluginDescriptionAttribute), false); 42 // exactly one attribute of the type PluginDescriptionAttribute must be given 43 if (pluginAttributes.Length != 1) { 44 throw new InvalidPluginException("Found multiple PluginDescriptionAttributes on type " + this.GetType()); 45 } 46 return (PluginDescriptionAttribute)pluginAttributes[0]; 85 47 } 86 48 } 87 49 88 50 #region IPlugin Members 89 /// <summary> 90 /// Gets the name of the plugin. 91 /// </summary> 51 /// <inheritdoc /> 92 52 public string Name { 93 53 get { 94 return name;54 return PluginDescriptionAttribute.Name; 95 55 } 96 56 } 97 57 98 /// <summary> 99 /// Gets the version of the plugin. 100 /// </summary> 58 /// <inheritdoc /> 101 59 public Version Version { 102 60 get { 103 return version; 61 var pluginAttribute = PluginDescriptionAttribute; 62 // if the version is not set in the attribute then the version of the assembly is used as default 63 if (string.IsNullOrEmpty(pluginAttribute.Version)) { 64 return this.GetType().Assembly.GetName().Version; 65 } else { 66 return new Version(pluginAttribute.Version); 67 } 104 68 } 105 69 } 106 70 107 /// <summary> 108 /// Gets the description of the plugin. 109 /// </summary> 71 /// <inheritdoc /> 110 72 public string Description { 111 73 get { 112 return description; 74 var pluginAttribute = PluginDescriptionAttribute; 75 // if the description is not explicitly set in the attribute then the name of the plugin is used as default 76 if (string.IsNullOrEmpty(pluginAttribute.Description)) { 77 return pluginAttribute.Name; 78 } else { 79 return pluginAttribute.Description; 80 } 113 81 } 114 82 } 115 83 116 84 /// <inheritdoc/> 117 public string[] Files {85 public IEnumerable<string> FileNames { 118 86 get { 119 return files; 87 // get all attributes of type PluginFileAttribute, multiple usage is possible 88 return from x in this.GetType().GetCustomAttributes(typeof(PluginFileAttribute), false) 89 let pluginFileAttr = (PluginFileAttribute)x 90 select pluginFileAttr.Filename; 120 91 } 121 92 } 122 93 123 /// <inherti doc>94 /// <inhertitdoc> 124 95 public virtual void OnLoad() { } 125 /// <inhertidoc>126 public virtual void OnInstall() { }127 /// <inhertidoc>128 public virtual void OnDelete() { }129 /// <inhertidoc>130 public virtual void OnPreUpdate() { }131 /// <inhertidoc>132 public virtual void OnPostUpdate() { }133 134 96 #endregion 135 97 -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/HeuristicLab.PluginInfrastructure.csproj
r1589 r2475 19 19 <UpgradeBackupLocation> 20 20 </UpgradeBackupLocation> 21 <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> 21 22 </PropertyGroup> 22 23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> … … 75 76 <ItemGroup> 76 77 <Reference Include="System" /> 78 <Reference Include="System.Core"> 79 <RequiredTargetFramework>3.5</RequiredTargetFramework> 80 </Reference> 77 81 <Reference Include="System.Data" /> 78 82 <Reference Include="System.Deployment" /> … … 83 87 <ItemGroup> 84 88 <Compile Include="ApplicationInfo.cs" /> 85 <Compile Include="AssemblyBuildDateAttribute.cs" /> 89 <Compile Include="Attributes\ApplicationDescriptionAttribute.cs" /> 90 <Compile Include="Attributes\AssemblyBuildDateAttribute.cs" /> 91 <Compile Include="Attributes\PluginDependencyAttribute.cs" /> 92 <Compile Include="Attributes\PluginDescriptionAttribute.cs" /> 93 <Compile Include="Attributes\PluginFileAttribute.cs" /> 86 94 <Compile Include="BaseClasses\ApplicationBase.cs" /> 87 95 <Compile Include="BaseClasses\PluginBase.cs" /> 88 <Compile Include="ClassInfoAttribute.cs" />89 96 <Compile Include="Interfaces\IApplication.cs" /> 90 97 <Compile Include="Interfaces\IControl.cs" /> … … 93 100 <Compile Include="PluginManager.cs" /> 94 101 <Compile Include="PluginManagerActionEventArgs.cs" /> 95 <Compile Include="DependencyAttribute.cs" />96 102 <Compile Include="Interfaces\IPlugin.cs" /> 97 103 <Compile Include="DiscoveryService.cs" /> 98 <Compile Include="PluginFileAttribute.cs" />99 104 <Compile Include="PluginInfo.cs" /> 100 105 <Compile Include="Loader.cs" /> -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Interfaces/IApplication.cs
r242 r2475 29 29 Version Version { get; } 30 30 string Description { get;} 31 bool AutoRestart{ get; }31 bool RestartOnErrors { get; } 32 32 void Run(); 33 33 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs
r1229 r2475 30 30 /// assemblies of the plugin. Plugin developers can use the properties of this interface to store 31 31 /// plugin data (name, version, files, update location ...). 32 /// The methods OnLoad(), OnInstall(), OnDelete(), OnPreUpdate(), OnPostUpdate() are called by the framework 33 /// when the corresponding actions are executed. This mechanism allows that the plugin reacts to such 34 /// events. For instance to store plugin specific settings. 32 /// The method OnLoad() is called by the framework when the plugin is loaded (application start). 35 33 /// </summary> 36 interface IPlugin { 34 internal interface IPlugin { 35 /// <summary> 36 /// Gets the name of the plugin. 37 /// </summary> 37 38 string Name { get; } 39 /// <summary> 40 /// Gets the version of the plugin. 41 /// </summary> 38 42 Version Version { get; } 39 43 /// <summary> 40 /// a list of all files that are bundled with this plugin including all assembly files (*.dll)44 /// Gets all file names that are bundled with this plugin including all assembly files (*.dll) 41 45 /// </summary> 42 string[] Files { get; } 43 46 IEnumerable<string> FileNames { get; } 44 47 45 48 /// <summary> 46 49 /// Called by the framework whenever the plugin is loaded. 47 /// Plugins are loaded once at startup and then each timea new application is started from the starter.50 /// Plugins are loaded when a new application is started from the starter. 48 51 /// </summary> 49 52 void OnLoad(); 50 /// <summary>51 /// called by the framework after the plugin was successfully installed52 /// </summary>53 void OnInstall();54 /// <summary>55 /// called by the framework before the files of the plugin are deleted56 /// </summary>57 void OnDelete();58 /// <summary>59 /// called by the framework before the files of the plugin are deleted for an update60 /// OnPreUpdate() is sent only to the old instance of the plugin61 /// </summary>62 void OnPreUpdate();63 /// <summary>64 /// called by the framework after the updated files for the plugin have been installed65 /// OnPostUpdate() is sent only to the new updated instance of the plugin66 /// </summary>67 void OnPostUpdate();68 53 } 69 54 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/InvalidPluginException.cs
r1189 r2475 28 28 /// Exception class for invalid plugins. 29 29 /// </summary> 30 class InvalidPluginException : Exception { 30 internal class InvalidPluginException : Exception { 31 public InvalidPluginException(string message) : base(message) { } 31 32 } 32 33 } -
branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/Loader.cs
r2168 r2475 127 127 info.Version = application.Version; 128 128 info.Description = application.Description; 129 info.AutoRestart = application. AutoRestart;129 info.AutoRestart = application.RestartOnErrors; 130 130 info.PluginAssembly = application.GetType().Assembly.GetName().Name; 131 131 info.PluginType = application.GetType().Namespace + "." + application.GetType().Name; … … 380 380 string baseDir = AppDomain.CurrentDomain.BaseDirectory; 381 381 382 Array.ForEach<string>(plugin.File s, delegate(string file) {382 Array.ForEach<string>(plugin.FileNames, delegate(string file) { 383 383 string filename = pluginDir + "/" + file; 384 384 // always use \ as the directory separator
Note: See TracChangeset
for help on using the changeset viewer.