csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.4 KiB
99 lines
3.4 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using dnlib.DotNet;
|
|
using dnlib.DotNet.Emit;
|
|
using dnlib.DotNet.Writer;
|
|
|
|
public class RefAssemblyGenerator
|
|
{
|
|
static void PatchRefAssembly(string file)
|
|
{
|
|
|
|
var reader = typeof(RefAssemblyGenerator).Assembly.GetManifestResourceStream("avalonia.snk");
|
|
var snk = new byte[reader.Length];
|
|
reader.Read(snk, 0, snk.Length);
|
|
|
|
var def = AssemblyDef.Load(new MemoryStream(File.ReadAllBytes(file)));
|
|
|
|
foreach(var t in def.ManifestModule.Types)
|
|
ProcessType(t);
|
|
def.Write(file, new ModuleWriterOptions(def.ManifestModule)
|
|
{
|
|
StrongNameKey = new StrongNameKey(snk),
|
|
});
|
|
}
|
|
|
|
static void ProcessType(TypeDef type)
|
|
{
|
|
foreach (var nested in type.NestedTypes)
|
|
ProcessType(nested);
|
|
if (type.IsInterface)
|
|
{
|
|
var hideMethods = type.Name.EndsWith("Impl");
|
|
var injectMethod = hideMethods
|
|
|| type.CustomAttributes.Any(a =>
|
|
a.AttributeType.FullName.EndsWith("NotClientImplementableAttribute"));
|
|
|
|
if (hideMethods)
|
|
{
|
|
foreach (var m in type.Methods)
|
|
{
|
|
m.Attributes |= MethodAttributes.Public | MethodAttributes.Assembly;
|
|
m.Attributes ^= MethodAttributes.Public;
|
|
}
|
|
}
|
|
|
|
if(injectMethod)
|
|
{
|
|
type.Methods.Add(new MethodDefUser("NotClientImplementable",
|
|
new MethodSig(CallingConvention.Default, 0, type.Module.CorLibTypes.Void),
|
|
MethodAttributes.Assembly
|
|
| MethodAttributes.Abstract
|
|
| MethodAttributes.NewSlot
|
|
| MethodAttributes.HideBySig));
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void GenerateRefAsmsInPackage(string packagePath)
|
|
{
|
|
using (var archive = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.ReadWrite),
|
|
ZipArchiveMode.Update))
|
|
{
|
|
foreach (var entry in archive.Entries.ToList())
|
|
{
|
|
if (entry.FullName.StartsWith("ref/"))
|
|
entry.Delete();
|
|
}
|
|
|
|
foreach (var entry in archive.Entries.ToList())
|
|
{
|
|
if (entry.FullName.StartsWith("lib/"))
|
|
{
|
|
if (entry.Name.EndsWith(".dll"))
|
|
{
|
|
using (Helpers.UseTempDir(out var temp))
|
|
{
|
|
var file = Path.Combine(temp, entry.Name);
|
|
entry.ExtractToFile(file);
|
|
PatchRefAssembly(file);
|
|
archive.CreateEntryFromFile(file, "ref/" + entry.FullName.Substring(4));
|
|
|
|
}
|
|
}
|
|
else if (entry.Name.EndsWith(".xml"))
|
|
{
|
|
var newEntry = archive.CreateEntry("ref/" + entry.FullName.Substring(4),
|
|
CompressionLevel.Optimal);
|
|
using (var src = entry.Open())
|
|
using (var dst = newEntry.Open())
|
|
src.CopyTo(dst);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|