这是一个围绕游戏服务器环绕Eco的项目。
只有在尝试在Eco.Core程序集上运行AssemblyDefinition.Write()
时才会发生此异常。
我也找不到依赖版本,文件版本等方面的任何差异。 Eco.Core组件和其他组件之间。
使用Costura将所有游戏程序集压缩为资源到实际的启动器文件中。
其他信息:
项目链接:https://github.com/RocketMod/Rocket.Eco/tree/dev/Rocket.Eco.Launcher
Unhandled Exception: Mono.Cecil.ResolutionException: Failed to resolve
System.Reflection.BindingFlags
at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
at Mono.Cecil.MetadataBuilder.GetConstantType(TypeReference constant_type, Object constant)
at Mono.Cecil.MetadataBuilder.AddConstant(IConstantProvider owner, TypeReference type)
at Mono.Cecil.MetadataBuilder.AddField(FieldDefinition field)
at Mono.Cecil.MetadataBuilder.AddFields(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddTypes()
at Mono.Cecil.MetadataBuilder.BuildTypes()
at Mono.Cecil.MetadataBuilder.BuildModule()
at Mono.Cecil.MetadataBuilder.BuildMetadata()
at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters parameters)
at Rocket.Eco.Launcher.Program.LoadAssemblyFromDefinition(AssemblyDefinition definition)
at System.Collections.Generic.List`1.ForEach(Action`1 action)
at Rocket.Eco.Launcher.Program.Main(String[] args)
以下是可能涉及的所有代码段:(是的,它对于StackOverflow问题很多,但您也可以使用顶部的项目链接通过GitHub查看它。)
//This is inside the implementation of IPatchingService.
public IEnumerable<AssemblyDefinition> Patch()
{
lock (lockObj)
{
foreach (AssemblyDefinition asmDef in assemblies)
{
foreach (IAssemblyPatch patch in patches)
{
foreach (ModuleDefinition modDef in asmDef.Modules)
{
TypeDefinition typeDef = modDef.Types.FirstOrDefault(x => x.FullName.Equals(patch.TargetType, StringComparison.InvariantCultureIgnoreCase));
if (typeDef == null)
continue;
patch.Patch(typeDef);
break;
}
}
}
//I hope this kills the Stream...
assemblies.ForEach(x => x.Dispose());
AssemblyDefinition[] asmArray = assemblies.ToArray();
assemblies.Clear();
patches.Clear();
return asmArray;
}
}
public sealed class CosturaAssemblyResolver : BaseAssemblyResolver
{
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
string actName = name.Name;
if (!CosturaHelper.Assemblies.TryGetValue(actName, out CosturaHelper.AssemblyData result))
return null;
if (result.Assembly != null)
return result.Assembly;
result.Stream.Position = 0;
try
{
AssemblyDefinition defn = AssemblyDefinition.ReadAssembly(result.Stream, new ReaderParameters()
{
AssemblyResolver = this
});
result.Assembly = defn;
return defn;
}
catch (ResolutionException e)
{
return null;
}
}
}
public static class CosturaHelper
{
internal static Dictionary<string, AssemblyData> Assemblies = new Dictionary<string, AssemblyData>(StringComparer.InvariantCultureIgnoreCase);
public static IEnumerable<AssemblyDefinition> ExtractCosturaAssemblies(AssemblyDefinition definition)
{
List<AssemblyDefinition> definitions = new List<AssemblyDefinition>();
definition.MainModule.Resources.Where(x => x.ResourceType == ResourceType.Embedded).Cast<EmbeddedResource>().Where(x => x.Name.EndsWith(".compressed") && x.Name.StartsWith("costura")).ForEach(x =>
{
using (Stream stream = x.GetResourceStream())
{
using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress))
{
MemoryStream memStream = new MemoryStream();
byte[] array = new byte[81920];
int count;
while ((count = deflateStream.Read(array, 0, array.Length)) != 0)
{
memStream.Write(array, 0, count);
}
Assemblies[x.Name.Replace(".dll.compressed", "").Replace("costura.", "")] = new AssemblyData(memStream, null);
}
}
});
CosturaAssemblyResolver resolver = new CosturaAssemblyResolver();
ReaderParameters parameters = new ReaderParameters()
{
AssemblyResolver = resolver
};
Assemblies.Keys.ForEach(x =>
{
AssemblyData asm = Assemblies[x];
if (asm.Assembly != null)
{
definitions.Add(asm.Assembly);
}
else
{
asm.Stream.Position = 0;
asm.Assembly = AssemblyDefinition.ReadAssembly(asm.Stream, parameters);
definitions.Add(asm.Assembly);
}
});
return definitions;
}
public static void DisposeStreams() => Assemblies.ForEach(x => x.Value.Stream.Dispose());
//plz add data classes like in Kotlin
public class AssemblyData
{
public AssemblyDefinition Assembly;
public Stream Stream;
public AssemblyData(Stream stream, AssemblyDefinition admdef)
{
Assembly = admdef;
Stream = stream;
}
}
}
public static void Main(string[] args)
{
IPatchingService patchingService = new PatchingService();
FileStream stream = File.OpenRead("EcoServer.exe");
AssemblyDefinition defn = AssemblyDefinition.ReadAssembly(stream);
CosturaHelper.ExtractCosturaAssemblies(defn).ForEach(x => patchingService.RegisterAssembly(x));
patchingService.RegisterPatch<UserPatch>();
patchingService.RegisterPatch<ChatManagerPatch>();
List<AssemblyDefinition> patches = patchingService.Patch().ToList();
patches.ForEach(x => Console.WriteLine(x.Name.Name));
//This fixes only ONE of the errors.
AssemblyDefinition ecoShared = patches.First(x => x.Name.Name.Equals("Eco.Shared", StringComparison.InvariantCultureIgnoreCase));
patches.Remove(ecoShared);
LoadAssemblyFromDefinition(ecoShared);
patches.ForEach(LoadAssemblyFromDefinition);
CosturaHelper.DisposeStreams();
patchingService.RegisterAssembly(defn);
patchingService.RegisterPatch<StartupPatch>();
patchingService.Patch().ForEach(LoadAssemblyFromDefinition);
stream.Dispose();
#if DEBUG
AppDomain.CurrentDomain.GetAssemblies().ForEach(x => Console.WriteLine(x.FullName));
#endif
AppDomain.CurrentDomain.AssemblyResolve -= GatherRocketDependencies;
AppDomain.CurrentDomain.GetAssemblies()
.First(x => x.GetName().Name.Equals("EcoServer"))
.GetType("Eco.Server.Startup")
.GetMethod("Start", BindingFlags.Static | BindingFlags.Public)
.Invoke(null, new object[]
{args.Where(x => !x.Equals("-extract", StringComparison.InvariantCultureIgnoreCase)).ToArray()});
Console.WriteLine("Houston, we have control!");
//Runtime.Bootstrap();
}
private static void LoadAssemblyFromDefinition(AssemblyDefinition definition)
{
using (MemoryStream stream = new MemoryStream())
{
//definition.MainModule.ImportReference(typeof(BindingFlags)); //Failed attempt to resolve System.Reflection.BindingFlags that it keeps complaining about.
definition.Write(stream);
stream.Position = 0; //Is this needed?
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
Assembly.Load(buffer);
}
}