-
Notifications
You must be signed in to change notification settings - Fork 19
/
BounceAssemblyRunner.cs
95 lines (77 loc) · 3.76 KB
/
BounceAssemblyRunner.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
namespace Bounce.Console {
[Serializable]
class BounceAssemblyRunner {
private readonly BeforeBounceScriptRunner BeforeBounceScriptRunner;
private string assemblyFileName;
private string[] arguments;
public BounceAssemblyRunner() {
BeforeBounceScriptRunner = new BeforeBounceScriptRunner();
}
public void Run(string[] args) {
try {
FindTargetsAssemblyAndRunBounce(args);
} catch (BounceConsoleException bce) {
bce.Explain(System.Console.Error);
Environment.Exit(1);
} catch (Exception e) {
System.Console.Error.WriteLine(e);
Environment.Exit(1);
}
}
private void FindTargetsAssemblyAndRunBounce(string[] args) {
var optionsAndArguments = GetAssemblyFileName(args);
BeforeBounceScriptRunner.RunBeforeBounceScript(optionsAndArguments);
assemblyFileName = optionsAndArguments.TargetsAssembly.Executable;
arguments = optionsAndArguments.RemainingArguments;
var appDomainSetup = new AppDomainSetup { ShadowCopyFiles = true.ToString() };
var appDomain = AppDomain.CreateDomain("Bounce", null, appDomainSetup);
try
{
//call back to transfer control to other app domain
appDomain.DoCallBack(AppDomainLoaderCallBack);
}
finally
{
AppDomain.Unload(appDomain);
}
}
private void AppDomainLoaderCallBack()
{
System.Console.WriteLine("- Loading bounce targets assembly (with shadow-copy enabled) from '" + assemblyFileName + "'.");
var assembly = Assembly.LoadFrom(assemblyFileName);
System.Console.WriteLine("- Targets assembly loaded from '" + assembly.Location + "'.");
var bounceAssemblyAndTargetsProperty = GetTargetsMemberFromAssembly(assembly);
RunAssembly(bounceAssemblyAndTargetsProperty, arguments);
}
private OptionsAndArguments GetAssemblyFileName(string[] args) {
return new TargetsAssemblyArgumentsParser().GetTargetsAssembly(args);
}
private void RunAssembly(BounceAssemblyAndTargetsProperty bounceAssemblyAndTargetsProperty, IEnumerable args) {
if (args == null) throw new ArgumentNullException("args");
Assembly bounceAssembly = bounceAssemblyAndTargetsProperty.BounceAssembly;
Type runnerType = bounceAssembly.GetType("Bounce.Framework.BounceRunner");
object runner = runnerType.GetConstructor(new Type[0]).Invoke(new object[0]);
runnerType.GetMethod("Run").Invoke(runner, new object[] { args, bounceAssemblyAndTargetsProperty.GetTargetsMethod });
}
BounceAssemblyAndTargetsProperty GetTargetsMemberFromAssembly(Assembly assembly) {
var allProperties = assembly.GetTypes().SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public));
foreach (var prop in allProperties) {
foreach (var attr in prop.GetCustomAttributes(false)) {
var attrType = attr.GetType();
if (attrType.FullName == "Bounce.Framework.TargetsAttribute") {
return new BounceAssemblyAndTargetsProperty { BounceAssembly = attrType.Assembly, GetTargetsMethod = prop };
}
}
}
throw new TargetsAttributeNotFoundException();
}
class BounceAssemblyAndTargetsProperty {
public MethodInfo GetTargetsMethod;
public Assembly BounceAssembly;
}
}
}