diff --git a/csharp/Framework/ConverterOptions.cs b/csharp/Framework/ConverterOptions.cs
index 089b73d..f4a4b2a 100644
--- a/csharp/Framework/ConverterOptions.cs
+++ b/csharp/Framework/ConverterOptions.cs
@@ -9,6 +9,7 @@ namespace OpenSvip.Framework
///
/// 由 OpenSVIP Framework 提供给工程转换器的转换选项。
///
+ [Serializable]
public class ConverterOptions
{
private readonly Dictionary OptionDictionary;
diff --git a/csharp/Framework/OpenSvip.Framework.csproj b/csharp/Framework/OpenSvip.Framework.csproj
index 7376c03..73810d9 100644
--- a/csharp/Framework/OpenSvip.Framework.csproj
+++ b/csharp/Framework/OpenSvip.Framework.csproj
@@ -46,6 +46,7 @@
+
diff --git a/csharp/Framework/TaskContainer.cs b/csharp/Framework/TaskContainer.cs
new file mode 100644
index 0000000..d725d23
--- /dev/null
+++ b/csharp/Framework/TaskContainer.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace OpenSvip.Framework
+{
+ public class TaskContainer : MarshalByRefObject
+ {
+ private IProjectConverter _inputConverter;
+
+ private IProjectConverter _outputConverter;
+
+ private ConverterOptions _inputOptions;
+
+ private ConverterOptions _outputOptions;
+
+ private static IProjectConverter LoadConverter(Plugin plugin)
+ {
+ var assembly = Assembly.LoadFrom(Path.Combine(PluginManager.PluginPath, plugin.LibraryPath));
+ var type = assembly.GetType(plugin.Converter);
+ return (IProjectConverter) Activator.CreateInstance(type);
+ }
+
+ public void Init(
+ Plugin inputPlugin,
+ Plugin outputPlugin,
+ ConverterOptions inputOptions,
+ ConverterOptions outputOptions)
+ {
+ _inputConverter = LoadConverter(inputPlugin);
+ _outputConverter = LoadConverter(outputPlugin);
+ _inputOptions = inputOptions;
+ _outputOptions = outputOptions;
+ }
+
+ public void Run(string importPath, string exportPath)
+ {
+ Warnings.AddWarning("Hello!");
+ _outputConverter.Save(exportPath, _inputConverter.Load(importPath, _inputOptions), _outputOptions);
+ }
+
+ public Warning[] GetWarnings()
+ {
+ return Warnings.GetWarnings();
+ }
+
+ public void ClearWarnings()
+ {
+ Warnings.ClearWarnings();
+ }
+ }
+}
diff --git a/csharp/Framework/Warnings.cs b/csharp/Framework/Warnings.cs
index 9085faf..af7ebd6 100644
--- a/csharp/Framework/Warnings.cs
+++ b/csharp/Framework/Warnings.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
@@ -27,6 +28,7 @@ public enum WarningTypes
[Description("未知")] Others
}
+ [Serializable]
public class Warning
{
public WarningTypes Type;
diff --git a/csharp/GUI/MainWindow.xaml.cs b/csharp/GUI/MainWindow.xaml.cs
index 5b5b251..71c86aa 100644
--- a/csharp/GUI/MainWindow.xaml.cs
+++ b/csharp/GUI/MainWindow.xaml.cs
@@ -9,6 +9,7 @@
using OpenSvip.Framework;
using System.Threading;
using System.Diagnostics;
+using System.Reflection;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.Windows.Input;
using OpenSvip.GUI.Config;
@@ -197,13 +198,38 @@ private void ExecuteTasks()
}
new Thread(() =>
{
+ // Prepare for execution
Model.ExecutionInProgress = true;
- var inputConverter = PluginManager.GetConverter(Model.SelectedInputPlugin.Identifier);
- var outputConverter = PluginManager.GetConverter(Model.SelectedOutputPlugin.Identifier);
foreach (var task in Model.TaskList)
{
task.PrepareForExecution();
}
+
+ // Construct options
+ var inputOptionDictionary = new Dictionary();
+ foreach (var option in Model.SelectedInputOptions)
+ {
+ inputOptionDictionary[option.OptionInfo.Name] = option.OptionValue;
+ }
+ var outputOptionDictionary = new Dictionary();
+ foreach (var option in Model.SelectedOutputOptions)
+ {
+ outputOptionDictionary[option.OptionInfo.Name] = option.OptionValue;
+ }
+ var inputOptions = new ConverterOptions(inputOptionDictionary);
+ var outputOptions = new ConverterOptions(outputOptionDictionary);
+
+ // Create sandbox for tasks
+ var domain = AppDomain.CreateDomain("TaskExecution");
+ var container = (TaskContainer)domain.CreateInstanceAndUnwrap(
+ Assembly.GetAssembly(typeof(TaskContainer)).FullName,
+ typeof(TaskContainer).ToString());
+ container.Init(
+ Model.SelectedInputPlugin,
+ Model.SelectedOutputPlugin,
+ inputOptions,
+ outputOptions);
+
var skipSameFilename = Model.OverWriteOption == OverwriteOptions.Skip;
var askBeforeOverwrite = Model.OverWriteOption == OverwriteOptions.Ask;
foreach (var task in Model.TaskList)
@@ -228,23 +254,8 @@ private void ExecuteTasks()
continue;
}
}
-
- var inputOptionDictionary = new Dictionary();
- foreach (var option in Model.SelectedInputOptions)
- {
- inputOptionDictionary[option.OptionInfo.Name] = option.OptionValue;
- }
- var outputOptionDictionary = new Dictionary();
- foreach (var option in Model.SelectedOutputOptions)
- {
- outputOptionDictionary[option.OptionInfo.Name] = option.OptionValue;
- }
- outputConverter.Save(
- task.ExportPath,
- inputConverter.Load(
- task.ImportPath,
- new ConverterOptions(inputOptionDictionary)),
- new ConverterOptions(outputOptionDictionary));
+ // Run the container
+ container.Run(task.ImportPath, task.ExportPath);
}
catch (Exception e)
{
@@ -252,7 +263,7 @@ private void ExecuteTasks()
task.Error = e.Message;
continue;
}
- var warnings = Warnings.GetWarnings();
+ var warnings = container.GetWarnings();
if (warnings.Any())
{
task.Status = TaskStates.Warning;
@@ -260,13 +271,17 @@ private void ExecuteTasks()
{
task.Warnings.Add(warning);
}
- Warnings.ClearWarnings();
+ container.ClearWarnings();
}
else
{
task.Status = TaskStates.Success;
}
}
+ // Unload the domain to release assembly files
+ AppDomain.Unload(domain);
+
+ // Things after execution
Model.ExecutionInProgress = false;
if (!Model.OpenExportFolder)
{
@@ -279,27 +294,27 @@ private void ExecuteTasks()
}).Start();
}
- public static RelayCommand ImportCommand = new RelayCommand(
+ public static readonly RelayCommand ImportCommand = new RelayCommand(
p => !p.Model.ExecutionInProgress,
p => p.FileMaskPanel_Click(null, null));
- public static RelayCommand ExportCommand = new RelayCommand(
+ public static readonly RelayCommand ExportCommand = new RelayCommand(
p => p.StartExecutionButton.IsEnabled,
p => p.StartExecutionButton_Click(null, null));
- public static RelayCommand BrowseAndExportCommand = new RelayCommand(
+ public static readonly RelayCommand BrowseAndExportCommand = new RelayCommand(
p => p.StartExecutionButton.IsEnabled,
p => p.BrowseAndExportMenu_Click(null, null));
- public static RelayCommand ResetCommand = new RelayCommand(
+ public static readonly RelayCommand ResetCommand = new RelayCommand(
p => !p.ExecutionInProgress,
p => p.TaskList.Clear());
- public static RelayCommand AboutCommand = new RelayCommand(
+ public static readonly RelayCommand AboutCommand = new RelayCommand(
p => true,
p => p.AboutMenuItem_Click(null, null));
- public static RelayCommand ImportPluginMenuItemCommand = new RelayCommand(
+ public static readonly RelayCommand ImportPluginMenuItemCommand = new RelayCommand(
p =>
{
var model = (AppModel)p.DataContext;
@@ -317,7 +332,7 @@ private void ExecuteTasks()
((MainWindow)App.Current.MainWindow).Model.SelectedInputPluginIndex = index;
});
- public static RelayCommand ExportPluginMenuItemCommand = new RelayCommand(
+ public static readonly RelayCommand ExportPluginMenuItemCommand = new RelayCommand(
p => true,
p =>
{
@@ -331,7 +346,7 @@ private void ExecuteTasks()
((MainWindow)App.Current.MainWindow).Model.SelectedOutputPluginIndex = index;
});
- public static RelayCommand InstallPluginCommand = new RelayCommand(
+ public static readonly RelayCommand InstallPluginCommand = new RelayCommand(
p => !p.ExecutionInProgress,
p =>
{
@@ -419,7 +434,7 @@ private void ExecuteTasks()
}).Start();
});
- public static RelayCommand ManagePathsCommand = new RelayCommand(
+ public static readonly RelayCommand ManagePathsCommand = new RelayCommand(
p => !p.ExecutionInProgress,
p => PathManagerDialog.CreateDialog(p).ShowDialog());