Last active
July 5, 2016 11:55
-
-
Save unarist/418a07ec15e03f8da4d6f6907d43e020 to your computer and use it in GitHub Desktop.
Mono.Cecilだけでアセンブリをマージする
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Action<T> GetAssignMethod<T>(string field, object value) | |
| { | |
| var arg = Expression.Parameter(typeof(T)); | |
| var body = Expression.Assign(Expression.Field(arg, field), Expression.Constant(value)); | |
| return (Action<T>)Expression.Lambda(typeof(Action<T>), body, arg).Compile(); | |
| } | |
| void MoveItems<T>(ICollection<T> src, ICollection<T> dest, Func<T,bool> filter = null) | |
| { | |
| var items = filter != null ? src.Where(filter).ToList() : src.ToList(); | |
| items.ForEach(x => { src.Remove(x); dest.Add(x); }); | |
| } | |
| void VisitTypes(IEnumerable<TypeDefinition> rootset, Action<TypeDefinition> action) | |
| { | |
| var types = new Stack<TypeDefinition>(rootset); | |
| while (types.Any()) | |
| { | |
| var cur = types.Pop(); | |
| action(cur); | |
| cur.NestedTypes.ForEach(types.Push); | |
| } | |
| } | |
| void Main() | |
| { | |
| var src = AssemblyDefinition.ReadAssembly(typeof(MyExtensions).Assembly.Location, new ReaderParameters(ReadingMode.Immediate)); | |
| var dest = AssemblyDefinition.ReadAssembly(@"R:\hoge.exe"); | |
| var src_m = src.MainModule; | |
| var dest_m = dest.MainModule; | |
| // ReadingMode.Immediate でも読んでくれないデータを読み込む(MethodDef.Body) | |
| VisitTypes(src_m.Types, t => t.Methods.ForEach(m => m.Body?.GetHashCode())); | |
| // モジュール間で乗せ換え(moduleを書き換えないといけないもの) | |
| var fixmodule = GetAssignMethod<TypeReference>("module", dest_m); | |
| VisitTypes(src_m.Types, t => t.NestedTypes.ForEach(fixmodule)); | |
| src_m.GetTypeReferences().ForEach(fixmodule); | |
| var nativeTypes = | |
| from prop in typeof(TypeSystem).GetProperties() | |
| where prop.PropertyType == typeof(TypeReference) | |
| select (TypeReference)prop.GetValue(src_m.TypeSystem); | |
| nativeTypes.ForEach(fixmodule); | |
| // 名前空間の書き換え | |
| var new_ns = src.Name.Name; | |
| var oldref = dest_m.AssemblyReferences.First(x => x.FullName == src.FullName); | |
| dest_m.GetTypeReferences().Where(t => t.Scope == oldref).ForEach(t => t.Namespace = new_ns); | |
| VisitTypes(src_m.Types, t => t.Namespace = new_ns); | |
| // モジュール間で乗せ換え(Attach/Detachが必要なもの) | |
| MoveItems(src_m.AssemblyReferences, dest_m.AssemblyReferences, t => !dest_m.AssemblyReferences.Any(tt => t.FullName == tt.FullName)); | |
| MoveItems(src_m.Types, dest_m.Types, t => !dest_m.Types.Any(tt => t.FullName == tt.FullName)); | |
| MoveItems(src_m.Resources, dest_m.Resources); | |
| // 旧アセンブリへの参照を自分自身への参照に | |
| oldref.Name = dest.Name.Name; | |
| oldref.Version = dest.Name.Version; | |
| oldref.Culture = dest.Name.Culture; | |
| oldref.PublicKeyToken = dest.Name.PublicKeyToken; | |
| dest.Write(@"r:\dest.exe"); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment