forked from dotnetcore/WebApiClient
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CeAssembly.cs
159 lines (143 loc) · 4.78 KB
/
CeAssembly.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using Mono.Cecil;
using System;
using System.IO;
using System.Linq;
namespace WebApiClient.BuildTask
{
/// <summary>
/// 表示程序集
/// </summary>
class CeAssembly : IDisposable
{
/// <summary>
/// 日志
/// </summary>
private readonly Logger logger;
/// <summary>
/// 程序集
/// </summary>
private readonly AssemblyDefinition assembly;
/// <summary>
/// 获取所有已知类型
/// </summary>
public TypeDefinition[] KnowTypes { get; private set; }
/// <summary>
/// 获取主模块
/// </summary>
public ModuleDefinition MainMdule { get; private set; }
/// <summary>
/// 程序集
/// </summary>
/// <param name="fileName">文件路径</param>
/// <param name="searchDirectories">依赖项搜索目录</param>
/// <param name="logger">日志</param>
/// <exception cref="FileNotFoundException"></exception>
public CeAssembly(string fileName, string[] searchDirectories, Logger logger)
{
if (File.Exists(fileName) == false)
{
throw new FileNotFoundException("找不到文件编译输出的程序集");
}
var resolver = new DefaultAssemblyResolver();
foreach (var dir in searchDirectories)
{
logger.Message("添加搜索目录", dir);
resolver.AddSearchDirectory(dir);
}
var parameter = new ReaderParameters
{
ReadWrite = true,
ReadSymbols = true,
AssemblyResolver = resolver
};
this.logger = logger;
this.assembly = AssemblyDefinition.ReadAssembly(fileName, parameter);
this.MainMdule = this.assembly.MainModule;
this.KnowTypes = this.MainMdule
.AssemblyReferences
.Select(asm => this.ResolveAssemblyNameReference(resolver, asm))
.Where(item => item != null)
.SelectMany(item => item.GetTypes())
.ToArray();
}
/// <summary>
/// 解析依赖项
/// </summary>
/// <param name="resolver">解析器</param>
/// <param name="assembly">依赖的程序集</param>
/// <returns></returns>
private ModuleDefinition ResolveAssemblyNameReference(DefaultAssemblyResolver resolver, AssemblyNameReference assembly)
{
try
{
return resolver.Resolve(assembly).MainModule;
}
catch (Exception ex)
{
logger.Message(ex.Message);
return null;
}
}
/// <summary>
/// 写入代理类型
/// </summary>
/// <returns></returns>
public bool WirteProxyTypes()
{
var httpApiInterfaces = this.assembly
.MainModule
.GetTypes()
.Select(item => new CeInterface(this, item))
.Where(item => item.IsHttpApiInterface())
.ToArray();
var willSave = false;
foreach (var @interface in httpApiInterfaces)
{
var proxyType = new CeProxyType(this, @interface).Build();
if (this.IsDefinded(proxyType) == true)
{
continue;
}
this.logger.Message("正在写入IL", proxyType.FullName);
if (proxyType.DeclaringType != null)
{
proxyType.DeclaringType.NestedTypes.Add(proxyType);
}
else
{
this.assembly.MainModule.Types.Add(proxyType);
}
willSave = true;
}
if (willSave == true)
{
this.logger.Message("正在保存修改", this.assembly.FullName);
var parameters = new WriterParameters
{
WriteSymbols = true
};
this.assembly.Write(parameters);
}
return willSave;
}
/// <summary>
/// 返回类型是否在模块中已声明
/// </summary>
/// <param name="typeDefinition">类型</param>
/// <returns></returns>
public bool IsDefinded(TypeDefinition typeDefinition)
{
return this.assembly
.MainModule
.GetTypes()
.Any(item => item.FullName == typeDefinition.FullName);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
this.assembly.Dispose();
}
}
}