Giter Site home page Giter Site logo

monomod / monomod Goto Github PK

View Code? Open in Web Editor NEW
716.0 21.0 94.0 12.85 MB

C# modding swiss army knife, powered by cecil.

Home Page: https://monomod.dev/

License: MIT License

C# 98.86% PowerShell 0.06% Assembly 0.81% C++ 0.02% JavaScript 0.25%
c-sharp mono cecil net-framework patching modding cross-platform cil msil detours

monomod's Introduction

MonoMod

MonoMod Discord General purpose .NET assembly modding "basework", powered by cecil.
MIT-licensed.

Build status Deployment status

GitHub: All NuGet: Patcher NuGet: Utils NuGet: RuntimeDetour NuGet: HookGen
GitHub releases Core Utils RuntimeDetour HookGen
Version Version Version Version Version

... or download fresh build artifacts for the last commit.

Sections

Special thanks to my patrons on Patreon:


Introduction

MonoMod is a modding "basework" (base tools + framework).
Mods / mod loaders for the following games are already using it in one way or another:

It consists of the following modular components:

  • MonoMod.Patcher: The ahead-of-time MonoMod patcher and relinker.
  • MonoMod.Utils: Utilities and helpers that not only benefit MonoMod, but also mods in general. It contains classes such as PlatformDetection, FastReflectionHelper, DynamicMethodHelper, DynamicMethodDefinition, DynDll and the ModInterop namespace.
  • MonoMod.DebugIL: Enable IL-level debugging of third-party assemblies in Visual Studio / MonoDevelop.
  • MonoMod.Core: The core upon which runtime method detouring is built.
  • MonoMod.RuntimeDetour: A flexible and easily extensible runtime detouring library, supporting x86/x86_64 on .NET Framework, .NET Core, and Mono.
  • MonoMod.RuntimeDetour.HookGen: A utility to generate a "hook helper .dll" for any IL assembly. This allows you to hook methods in runtime mods as if they were events. Built with MonoMod and RuntimeDetour.
  • MonoMod.Backports: A collection of BCL backports, enabling the use of many new language and library features, as far back as .NET Framework 3.5.

Why?

  • Cross-version compatibility, even with obfuscated assemblies.
  • Cross-platform compatibility, even if the game uses another engine (f.e. Celeste uses XNA on Windows, FNA on macOS and Linux).
  • Use language features which otherwise wouldn't be supported (f.e. C# 7 in Unity 4.3).
  • Patch on the player's machine with a basic mod installer. No need to pre-patch, no redistribution of game data, no copyright violations.
  • With HookGen, runtime hooks are as simple as On.Namespace.Type.Method += (orig, a, b, c) => { /* ... */ }
  • With HookGen IL, you can manipulate IL at runtime and even inline C# delegate calls between instructions.
  • Modularity allows you to mix and match. Use only what you need!

Debugging mods that use MonoMod

See Debugging.

monomod's People

Contributors

0x0ade avatar azure-pipelines[bot] avatar bbepis avatar bluecheetah001 avatar chicken-bones avatar fifty-six avatar ghorsington avatar iamwyza avatar jackpendarvesread avatar jborean93 avatar js6pak avatar keboo avatar kevzhao2 avatar leo60228 avatar mewnojs avatar mirsario avatar nike4613 avatar opl- avatar popax21 avatar seresharp avatar snipundercover avatar windows10ce avatar zatherz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

monomod's Issues

HookGen not creating events for private methods

Description

HookGen doesn't seem to create events for private methods. I'm trying to patch The Long Dark's Assembly-CSharp.dll.

Example

On.GameManager.GetVersionString += (orig) => string.Empty; //This code works, as GetVersiongString is a public method.
On.GameManager.HandleCheckpointSaveRequest += (orig, self) => { }; //This doesn't, as HandleCheckpointSaveRequest is a private method.

EventDefinition / EventReference not taken into account

For some reason MonoMod is changing how events are being migrated slightly. I don't know that it actually changes their functionality. But it seems to take something that is fairly simple and makes it exceptionally verbose.

        [HookInfo("Called at the end of the attack function", "HeroController.Attack")]
        public event AfterAttackHandler AfterAttackHook;

        public void AfterAttack(AttackDirection dir)
        {
            AfterAttackHook?.Invoke(dir);
        }

is instead moved into the new assembly as:

[MonoModAdded]
public void AfterAttack(AttackDirection dir)
{
	AfterAttackHandler afterAttackHook = this.AfterAttackHook;
	if (afterAttackHook == null)
	{
		return;
	}
	afterAttackHook(dir);
}
[MonoModAdded]
[CompilerGenerated]
public void add_AfterAttackHook(AfterAttackHandler value)
{
	AfterAttackHandler afterAttackHandler = this.AfterAttackHook;
	AfterAttackHandler afterAttackHandler2;
	do
	{
		afterAttackHandler2 = afterAttackHandler;
		AfterAttackHandler value2 = (AfterAttackHandler)Delegate.Combine(afterAttackHandler2, value);
		afterAttackHandler = Interlocked.CompareExchange<AfterAttackHandler>(ref this.AfterAttackHook, value2, afterAttackHandler2);
	}
	while (afterAttackHandler != afterAttackHandler2);
}
[MonoModAdded]
[CompilerGenerated]
public void remove_AfterAttackHook(AfterAttackHandler value)
{
	AfterAttackHandler afterAttackHandler = this.AfterAttackHook;
	AfterAttackHandler afterAttackHandler2;
	do
	{
		afterAttackHandler2 = afterAttackHandler;
		AfterAttackHandler value2 = (AfterAttackHandler)Delegate.Remove(afterAttackHandler2, value);
		afterAttackHandler = Interlocked.CompareExchange<AfterAttackHandler>(ref this.AfterAttackHook, value2, afterAttackHandler2);
	}
	while (afterAttackHandler != afterAttackHandler2);
}

Stub .ctor with [MonoModIgnore] still being patched?

I have a class structure like that:

public class GUILayoutUtility
{
    static GUILayoutUtility() { //static ctor}
    internal sealed class LayoutCache
    {
        //ctors and vars
    }
}

// multiple other classes referenced in the class data above
internal class GUILayoutEntry, etc
{
}

Because they are all internal I cannot reference them so I create stubs with [MonoModIgnore]

[MonoModIgnore]
internal sealed class LayoutCache
{
	[MonoModIgnore]
	somefield
}

Original looks like this:
image

And patched looks like this:
image

What gives and how can I avoid this?

Question: Injection

Is it possible to add statements in the middle of a method with this framework? This stuff is great for replacing/appending/prepending methods, but I have a few cases where I need to put stuff in the middle of a method. I'd prefer to not have to copy the entire method from the original, but understand if this is outside the scope of this tool.

Crashed when creating a `DynamicData` with struct containing getters in Mono

Description

In mono, creating a DynamicData instance with a struct containing getters / properties will throw a System.InvalidProgramException.

MonoMod version: 21.8.19.1

Mono version:

$ mono --version
Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50 UTC 2020)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        Interpreter:   yes
        LLVM:          supported, not enabled.
        Suspend:       hybrid
        GC:            sgen (concurrent by default)

Example

This is compiled on Windows with target framework sets to 4.5.2, and ran with mono.

using MonoMod.Utils;

namespace ConsoleApp {
    public struct StructWithGetter {
        public int A => 1;

    }

    internal class Program {
        public static void Main(string[] args) {
            StructWithGetter obj = new StructWithGetter();
            DynamicData dynamicData = new DynamicData(obj);
        }
    }
}
System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:FastReflection<ConsoleApp.StructWithGetter::get_A> (object,object[]): IL_0006: call      0x00000003
  at (wrapper managed-to-native) System.Delegate.CreateDelegate_internal(System.Type,object,System.Reflection.MethodInfo,bool)
  at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) [0x00357] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method) [0x00000] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at System.Reflection.Emit.DynamicMethod.CreateDelegate (System.Type delegateType, System.Object target) [0x0001d] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at MonoMod.Utils.Extensions.CreateDelegate (System.Reflection.MethodBase method, System.Type delegateType, System.Object target) [0x00027] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.Extensions.CreateDelegate (System.Reflection.MethodBase method, System.Type delegateType) [0x00000] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.FastReflectionHelper._CreateFastDelegate (System.Reflection.MethodBase method, System.Boolean directBoxValueAccess) [0x00284] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.FastReflectionHelper.GetFastDelegate (System.Reflection.MethodInfo method, System.Boolean directBoxValueAccess) [0x00011] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.DynamicData+_Cache_..ctor (System.Type targetType) [0x001c8] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.DynamicData..ctor (System.Type type, System.Object obj, System.Boolean keepAlive) [0x00030] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at MonoMod.Utils.DynamicData..ctor (System.Object obj) [0x00007] in <59cbbd867fb04515abea4f0e92b83cc8>:0 
  at ConsoleApp.Program.Main (System.String[] args) [0x00009] in <41ded9052c1e45cd9047475c53281ae4>:0 

RuntimeDetour method hooks: the orig method receives an incorrect parameter on Steam Linux only

Description

I'm hooking this method in Celeste (OuiChapterPanel class):

private IEnumerator IncrementStatsDisplay(AreaModeStats modeStats, AreaModeStats newModeStats, bool doHeartGem, bool doStrawberries, bool doDeaths, bool doRemixUnlock)

This method is a coroutine, that I enumerate until it is done, to add some more behavior after it.

This works as expected on Windows, but when testing on Linux (Steam version / MonoKickstart) it seems that when I call the orig method, it receives doRemixUnlock = true, even when I pass false to it. (This has a visible effect when installing this mod and exiting a level: the B-side unlock animation plays, even when the B-side is already unlocked.)

Tested with Everest 1368 (MonoMod 20.1.1.4).

Example

On.Celeste.OuiChapterPanel.IncrementStatsDisplay += ModOuiChapterPanelIncrementStatsDisplay;
IL.Celeste.OuiChapterPanel.IncrementStatsDisplay += debugHook;

// hook on the method itself
private IEnumerator ModOuiChapterPanelIncrementStatsDisplay(On.Celeste.OuiChapterPanel.orig_IncrementStatsDisplay orig, OuiChapterPanel self, AreaModeStats modeStats, 
    AreaModeStats newModeStats, bool doHeartGem, bool doStrawberries, bool doDeaths, bool doRemixUnlock) {

    Logger.Log("test1", $"doRemixUnlock = {doRemixUnlock}");

    IEnumerator origMethod = orig(self, modeStats, newModeStats, doHeartGem, doStrawberries, doDeaths, doRemixUnlock);
    while(origMethod.MoveNext()) yield return origMethod.Current;
}

// IL hook helping with debugging
private void debugHook(ILContext il) {
    ILCursor cursor = new ILCursor(il);
    cursor.Emit(OpCodes.Ldarg_S, (byte) 6);
    cursor.EmitDelegate<Action<bool>>(param => Logger.Log("test2", $"doRemixUnlock = {param}"));
}

Gives that on Windows (Steam FNA):

[test1] doRemixUnlock = False
[test2] doRemixUnlock = False

and this on Linux (Steam MonoKickstart):

[test1] doRemixUnlock = False
[test2] doRemixUnlock = True

Invalid IL instructions when patching in dictionary

It appears bd9af67 introduced a regression. This code gets successfully patched in on the previous commit:

        private Dictionary<string, Ending> _endings = new Dictionary<string, Ending>();

        public void UpdateEndings(IEnumerable<Hashtable> endingsData)
        {
            _endings = new Dictionary<string, Ending>();
            foreach (var endingData in endingsData)
            {
                _endings.Add(
                    endingData.GetString("id"),
                    new Ending(
                        endingData.GetString("id"),
                        endingData.GetString("title"),
                        endingData.GetString("description"),
                        endingData.GetString("image"),
                        (EndingFlavour) Enum.Parse(typeof(EndingFlavour), endingData.GetString("flavour")),
                        endingData.GetString("anim"),
                        null));
            }
        }

From this commit onwards, when I try to patch this into a Unity game, I get this traceback:

InvalidProgramException: Invalid IL code in Compendium:UpdateEndings (System.Collections.Generic.IEnumerable`1<System.Collections.Hashtable>): IL_0093: brtrue.s  IL_0114


  at ContentImporter.PopulateCompendium (ICompendium compendium) [0x00000] in <filename unknown>:0 
  at MenuScreenController.orig_InitialiseServices () [0x00000] in <filename unknown>:0 
  at MenuScreenController.InitialiseServices () [0x00000] in <filename unknown>:0 
  at MenuScreenController.Start () [0x00000] in <filename unknown>:0 ```

(Thank you very much for all the work you put into this, by the way!)

Crash caused by `<PrivateImplementationDetails>` in `MonoMod.MonoModRules`

Description

MonoMod will crash if a method in MonoMod.MonoModRules contains <PrivateImplementationDetails> called during patch. Mostly because of initializing an array of primitive types or having a switch with more than 6 case and the compiler optimizes the code to <PrivateImplementationDetails>.

MonoMod version: 21.6.21.1

Example

SharpLab link

namespace MonoMod {
    public static class MonoModRules {
        static MonoModRules() {
            bool[] boolArray = {true, true, true, true, true, true, true, true};
            byte[] byteArray = {1, 2, 3};
            sbyte[] sbyteArray = {-1, 2, -3};
            char[] charArray = {'a', 'b', 'c'};
            short[] shortArray = {-1, 2, -3};
            ushort[] ushortArray = {1, 2, 3};
            int[] intArray = {-1, 2, -3};
            nint[] nintArray = {-1, 2, -3};
            uint[] uintArray = {1, 2, 3};
            nuint[] nuintArray = {1, 2, 3};
            long[] longArray = {-1, 2, -3};
            ulong[] ulongArray = {1, 2, 3};
            float[] floatArray = {-1, 2, -3};
            double[] doubleArray = {-1, 2, -3};
            string str = "a";
            switch (str) {
                case "a":
                    break;
                case "b":
                    break;
                case "c":
                    break;
                case "d":
                    break;
                case "e":
                    break;
                case "f":
                    break;
                case "g":
                    break;
            }
        }
    }
}

Compile this code to MonoMod.PrivateImplementationDetails.mm.dll and run MonoMod.exe MonoMod.exe, then MonoMod will crash with the following log:

MonoMod 21.6.21.1
[MonoMod] Reading input file into module.
[MonoMod] [Main] Scanning for mods in directory.
[MonoMod] [ReadMod] Loading mod dir: D:\My Documents\Rider\PrivateImplementationDetailsTest\PrivateImplementationDetailsTest.Mod.mm\bin\net452
[MonoMod] [ReadMod] Loading mod: D:\My Documents\Rider\PrivateImplementationDetailsTest\PrivateImplementationDetailsTest.Mod.mm\bin\net452\MonoMod.PrivateImplementationDetailsTest.mm.dll
[MonoMod] [Main] mm.AutoPatch();
[MonoMod] [AutoPatch] Parsing rules in loaded mods
[MonoMod] [RulesModder] [Write] Writing modded module into output stream.
System.TypeInitializationException: The type initializer for 'MonoMod.MonoModRules' threw an exception. ---> System.MissingFieldException: Field not found: '<PrivateImplementationDetails>.039058C6F2C0CB492C533B0A4D14EF77CC0F78ABCCCED5287D84A1A2011CFB81'.
   at MonoMod.MonoModRules..cctor()
   --- End of inner exception stack trace ---
   at System.Runtime.CompilerServices.RuntimeHelpers._RunClassConstructor(RuntimeType type)
   at MonoMod.InlineRT.MonoModRulesManager.ExecuteRules(MonoModder self, TypeDefinition orig)
   at MonoMod.MonoModder.ParseRules(ModuleDefinition mod)
   at MonoMod.MonoModder.AutoPatch()
   at MonoMod.Program.Main(String[] args)

mscorlib not found on some Linux installations

Can't replicate the issue, but this has been reported to me by @sammko:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> MonoMod.RelinkFailedException: MonoMod failed relinking System.Void (context: System.Void Monocle.Coroutine::Jump()) ---> MonoMod.RelinkTargetNotFoundException: MonoMod relinker failed finding System.Void (context: System.Void Monocle.Coroutine::Jump())

The issue vanished after copying mscorlib.dll relative to MonoMod, even though it should find it out of the box:

[sammko:~] λ csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> typeof(object).Assembly.Location 
"/usr/lib/mono/4.5/mscorlib.dll"                          
csharp>                                                   
                                                          
[sammko:~] λ mono --version
Mono JIT compiler version 5.4.1 (makepkg/e66d9abbb27 Thu Nov  9 22:28:33 CET 2017)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
    TLS:           __thread
    SIGSEGV:       normal
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none
    Misc:          softdebug 
    LLVM:          supported, not enabled.
    GC:            sgen (concurrent by default)
[sammko:~] λ file /usr/lib/mono/4.5/mscorlib.dll
/usr/lib/mono/4.5/mscorlib.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows

Inject IDetour

Description

Similar to how trampolines are injected.

static void Detour(Action orig, IDetor detour)
{
    // custom logic depending on executing method
}

Example

In my case, I'm using a single detour method for replacing multiple original methods and want to know which method I'm replacing.

private static MethodBase methodToRun = GetType().GetMethod(nameof(Detour));
private static Dictionary<IDetour, object> objectsToReturn = new();

// Makes the specified method always return the specified value.
public static void Returns(this MethodBase methodToReplace, object objectToReturn)
{
    var detour = new Detour(methodToReplace, methodToRun); // not sure yet which implementation I should use
    objectsToReturn[detour] = objectToReturn;
}

private static object Detour(IDetor detour)
{
    return objectsToReturn[detour];
}

Alternatives

If that's not possible for some reason, the alternative would be MethodBase origMethod. Similar is done in Harmony which works fine for me but I need a more low-level library.

Constructors don't seem to get patched in a patch_<name> class

I've been trying to patch a class from GILES, specifically GILES.Serialization.pb_SceneNode, in order to do this, i've been trying to patch the constructor, but according to a decompile, the constructors don't actually get patched, while any other non-constructor methods i've targeted do (e.g. GetObjectData() gets patched fine, constructors do not).
Here's my code i'm trying to patch in

namespace GILES.Serialization {
    public class patch_pb_SceneNode : ISerializable {
        public string name;
        public pb_Transform transform;
        public List<pb_SceneNode> children;
        public pb_MetaData metadata;
        public List<pb_ISerializable> components;
        public List<string> customComponents;
        public patch_pb_SceneNode(GameObject root) {
            name = root.name;
            components = new List<pb_ISerializable>();
            customComponents = new List<string>();
            foreach (MonoBehaviour mono in root.GetComponents<MonoBehaviour>()) {
                foreach (object attribute in mono.GetType().GetCustomAttributes(true)) {
                    if (attribute.GetType() == typeof(GTTOD.LevelEditor.CustomEditorObject)) {
                        customComponents.Add(attribute.GetType().AssemblyQualifiedName);
                    }
                }
            }
            pb_MetaDataComponent pb_MetaDataComponent = root.GetComponent<pb_MetaDataComponent>();
            if (pb_MetaDataComponent == null) {
                pb_MetaDataComponent = root.AddComponent<pb_MetaDataComponent>();
            }
            metadata = pb_MetaDataComponent.metadata;
            if (metadata.assetType == AssetType.Instance) {
                foreach (Component component in root.GetComponents<Component>()) {
                    if (!(component == null) && !(component is Transform)) {
                        if (!component.GetType().GetCustomAttributes(true).Any((object x) => x is pb_JsonIgnoreAttribute)) {
                            components.Add(pb_Serialization.CreateSerializableObject<Component>(component));
                        }
                    }
                }
            }
            transform = new pb_Transform();
            transform.SetTRS(root.transform);
            children = new List<pb_SceneNode>();
            foreach (object obj in root.transform) {
                Transform transform = (Transform)obj;
                if (transform.gameObject.activeSelf) {
                    children.Add(new pb_SceneNode(transform.gameObject));
                }
            }
        }
        public patch_pb_SceneNode(SerializationInfo info, StreamingContext context) {
            name = (string)info.GetValue("name", typeof(string));
            customComponents = (List<string>)info.GetValue("customComponents", typeof(List<string>));
            transform = (pb_Transform)info.GetValue("transform", typeof(pb_Transform));
            children = (List<pb_SceneNode>)info.GetValue("children", typeof(List<pb_SceneNode>));
            metadata = (pb_MetaData)info.GetValue("metadata", typeof(pb_MetaData));
            if (metadata.assetType == AssetType.Instance) {
                components = (List<pb_ISerializable>)info.GetValue("components", typeof(List<pb_ISerializable>));
            }
        }

        public extern void orig_GetObjectData(SerializationInfo info, StreamingContext context);
        public void GetObjectData(SerializationInfo info, StreamingContext context) {
            info.AddValue("customComponents", customComponents, typeof(List<string>));
            orig_GetObjectData(info, context);
        }
    }
}

Patching generic methods causes issues when importing them.

SIDENOTE: Using Mono.Cecil 0.9.5.0 because MonoDevelop refuses to find anything more up-to-date (although I've installed the NuGet plugin).

T: FezEngine.Tools.ServiceHelper
M: Microsoft.Xna.Framework.Game FezEngine.Tools.ServiceHelper::get_Game()
M: System.Void FezEngine.Tools.ServiceHelper::set_Game(Microsoft.Xna.Framework.Game)
M: System.Void FezEngine.Tools.ServiceHelper::InjectServices(System.Object)
M: System.Void FezEngine.Tools.ServiceHelper::orig_InitializeServices()
orig_InitializeServices is an orig_ method; ignoring...
M: System.Void FezEngine.Tools.ServiceHelper::InitializeServices()
Patching InitializeServices ...
Checking for already existing methods...
Method existing; creating copy...
Added copy of original method to System.Void FezEngine.Tools.ServiceHelper::orig_InitializeServices()
Storing method to main module...
M: T FezEngine.Tools.ServiceHelper::orig_Get()
orig_Get is an orig_ method; ignoring...
M: T FezEngine.Tools.ServiceHelper::Get()
Patching Get ...
Checking for already existing methods...
Method existing; creating copy...
Added copy of original method to T FezEngine.Tools.ServiceHelper::orig_Get()

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
  at Mono.Cecil.ImportGenericContext.MethodParameter (System.String method, Int32 position) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.MetadataImporter.ImportTypeSpecification (Mono.Cecil.TypeReference type, ImportGenericContext context) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.MetadataImporter.ImportType (Mono.Cecil.TypeReference type, ImportGenericContext context) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.ModuleDefinition.Import (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.FindType (Mono.Cecil.TypeReference type, Boolean fallbackToImport) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.FindType (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.PatchMethod (Mono.Cecil.MethodDefinition method) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.PatchModule (Mono.Cecil.ModuleDefinition mod) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.Patch () [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
  at Mono.Cecil.ImportGenericContext.MethodParameter (System.String method, Int32 position) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.MetadataImporter.ImportTypeSpecification (Mono.Cecil.TypeReference type, ImportGenericContext context) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.MetadataImporter.ImportType (Mono.Cecil.TypeReference type, ImportGenericContext context) [0x00000] in <filename unknown>:0 
  at Mono.Cecil.ModuleDefinition.Import (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.FindType (Mono.Cecil.TypeReference type, Boolean fallbackToImport) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.FindType (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.PatchMethod (Mono.Cecil.MethodDefinition method) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.PatchModule (Mono.Cecil.ModuleDefinition mod) [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.Patch () [0x00000] in <filename unknown>:0 
  at MonoMod.MonoMod.Main (System.String[] args) [0x00000] in <filename unknown>:0 

MonoMod.RuntimeDetour Build Failed!!

How i can fix this?

Error Log:

1>------ Build started: Project: MonoMod.Utils, Configuration: Debug Any CPU ------
1>DynDll.cs(52,17,52,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(52,35,52,43): error CS0103: The name 'Platform' does not exist in the current context
1>Cil\ILReferenceBag.cs(74,20,74,43): error CS0246: The type or namespace name 'DynamicMethodDefinition' could not be found (are you missing a using directive or an assembly reference?)
1>Cil\ILReferenceBag.cs(74,60,74,83): error CS0246: The type or namespace name 'DynamicMethodDefinition' could not be found (are you missing a using directive or an assembly reference?)
1>DynDll.cs(101,17,101,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(101,35,101,43): error CS0103: The name 'Platform' does not exist in the current context
1>DynDll.cs(122,17,122,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(122,35,122,43): error CS0103: The name 'Platform' does not exist in the current context
1>DynDll.cs(152,17,152,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(152,35,152,43): error CS0103: The name 'Platform' does not exist in the current context
1>Extensions.cs(154,44,154,58): error CS1061: 'MethodInfo' does not contain a definition for 'CreateDelegate' and no accessible extension method 'CreateDelegate' accepting a first argument of type 'MethodInfo' could be found (are you missing a using directive or an assembly reference?)
1>Cil\ILContext.cs(60,20,60,39): error CS1061: 'MethodDefinition' does not contain a definition for 'ConvertShortLongOps' and no accessible extension method 'ConvertShortLongOps' accepting a first argument of type 'MethodDefinition' could be found (are you missing a using directive or an assembly reference?)
1>Extensions.cs(181,50,181,64): error CS1061: 'MethodInfo' does not contain a definition for 'CreateDelegate' and no accessible extension method 'CreateDelegate' accepting a first argument of type 'MethodInfo' could be found (are you missing a using directive or an assembly reference?)
1>FastReflectionHelper.cs(19,78,19,83): error CS1061: 'MethodBase' does not contain a definition for 'GetID' and no accessible extension method 'GetID' accepting a first argument of type 'MethodBase' could be found (are you missing a using directive or an assembly reference?)
1>Cil\ILPatternMatchingExt.cs(401,50,401,55): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>FastReflectionHelper.cs(117,82,117,87): error CS1061: 'MethodBase' does not contain a definition for 'GetID' and no accessible extension method 'GetID' accepting a first argument of type 'MethodBase' could be found (are you missing a using directive or an assembly reference?)
1>Cil\ILPatternMatchingExt.cs(420,51,420,56): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(439,55,439,60): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(458,61,458,66): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(1091,52,1091,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1093,52,1093,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1108,52,1108,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1110,52,1110,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1137,67,1137,76): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1139,67,1139,71): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1150,53,1150,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(1165,56,1165,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1167,56,1167,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1182,53,1182,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1184,53,1184,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1206,52,1206,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1208,52,1208,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1234,52,1234,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1253,53,1253,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1272,52,1272,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1291,53,1291,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1310,54,1310,59): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1329,53,1329,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1344,52,1344,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1346,52,1346,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1431,50,1431,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1433,50,1433,55): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1448,53,1448,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1450,53,1450,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1472,54,1472,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1474,54,1474,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1622,56,1622,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1624,56,1624,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1639,56,1639,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1641,56,1641,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1656,55,1656,64): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1658,55,1658,60): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1729,56,1729,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1731,56,1731,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1753,55,1753,64): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1755,55,1755,60): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1947,52,1947,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(1966,56,1966,61): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(2104,54,2104,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2106,54,2106,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2121,58,2121,67): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2123,58,2123,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2170,53,2170,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2172,53,2172,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Done building project "MonoMod.Utils.csproj" -- FAILED.
1>Cil\ILContext.cs(60,20,60,39): error CS1061: 'MethodDefinition' does not contain a definition for 'ConvertShortLongOps' and no accessible extension method 'ConvertShortLongOps' accepting a first argument of type 'MethodDefinition' could be found (are you missing a using directive or an assembly reference?)
1>Cil\ILReferenceBag.cs(74,20,74,43): error CS0246: The type or namespace name 'DynamicMethodDefinition' could not be found (are you missing a using directive or an assembly reference?)
1>Cil\ILReferenceBag.cs(74,60,74,83): error CS0246: The type or namespace name 'DynamicMethodDefinition' could not be found (are you missing a using directive or an assembly reference?)
1>Cil\ILPatternMatchingExt.cs(401,50,401,55): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>DynDll.cs(52,17,52,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(52,35,52,43): error CS0103: The name 'Platform' does not exist in the current context
1>Cil\ILPatternMatchingExt.cs(420,51,420,56): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>DynDll.cs(101,17,101,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(101,35,101,43): error CS0103: The name 'Platform' does not exist in the current context
1>DynDll.cs(122,17,122,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(122,35,122,43): error CS0103: The name 'Platform' does not exist in the current context
1>Cil\ILPatternMatchingExt.cs(439,55,439,60): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>DynDll.cs(152,17,152,31): error CS0103: The name 'PlatformHelper' does not exist in the current context
1>DynDll.cs(152,35,152,43): error CS0103: The name 'Platform' does not exist in the current context
1>Cil\ILPatternMatchingExt.cs(458,61,458,66): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>FastReflectionHelper.cs(19,78,19,83): error CS1061: 'MethodBase' does not contain a definition for 'GetID' and no accessible extension method 'GetID' accepting a first argument of type 'MethodBase' could be found (are you missing a using directive or an assembly reference?)
1>FastReflectionHelper.cs(117,82,117,87): error CS1061: 'MethodBase' does not contain a definition for 'GetID' and no accessible extension method 'GetID' accepting a first argument of type 'MethodBase' could be found (are you missing a using directive or an assembly reference?)
1>Cil\ILPatternMatchingExt.cs(1091,52,1091,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1093,52,1093,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1108,52,1108,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1110,52,1110,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1137,67,1137,76): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1139,67,1139,71): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1150,53,1150,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(1165,56,1165,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1167,56,1167,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1182,53,1182,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1184,53,1184,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1206,52,1206,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1208,52,1208,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1234,52,1234,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1253,53,1253,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1272,52,1272,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1291,53,1291,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1310,54,1310,59): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1329,53,1329,58): error CS1503: Argument 2: cannot convert from 'System.Reflection.FieldInfo' to 'string'
1>Cil\ILPatternMatchingExt.cs(1344,52,1344,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1346,52,1346,57): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1431,50,1431,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1433,50,1433,55): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1448,53,1448,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1450,53,1450,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1472,54,1472,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1474,54,1474,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1622,56,1622,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1624,56,1624,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1639,56,1639,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1641,56,1641,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1656,55,1656,64): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1658,55,1658,60): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1729,56,1729,65): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1731,56,1731,61): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1753,55,1753,64): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1755,55,1755,60): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(1947,52,1947,57): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(1966,56,1966,61): error CS1503: Argument 2: cannot convert from 'System.Reflection.MethodBase' to 'string'
1>Cil\ILPatternMatchingExt.cs(2104,54,2104,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2106,54,2106,59): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2121,58,2121,67): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2123,58,2123,63): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2170,53,2170,62): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Cil\ILPatternMatchingExt.cs(2172,53,2172,58): error CS1503: Argument 2: cannot convert from 'System.Type' to 'string'
1>Done building project "MonoMod.Utils.csproj" -- FAILED.
2>------ Build started: Project: MonoMod.RuntimeDetour, Configuration: Debug Any CPU ------
2>CSC : error CS0006: Metadata file 'C:\Users\kikuk\Desktop\MonoMod-master\MonoMod.Utils\bin\Debug\net35\MonoMod.Utils.dll' could not be found
2>Done building project "MonoMod.RuntimeDetour.csproj" -- FAILED.
2>CSC : error CS0006: Metadata file 'C:\Users\kikuk\Desktop\MonoMod-master\MonoMod.Utils\bin\Debug\netstandard2.0\MonoMod.Utils.dll' could not be found
2>Done building project "MonoMod.RuntimeDetour.csproj" -- FAILED.
========== Build: 0 succeeded, 2 failed, 0 up-to-date, 0 skipped ==========

Crash when using NativeDetour and detouring to a method inside an inheriting class

Description

I've had a friend report that they're unable to use NativeDetour when the class that contains the method to detour to is inside a class that inherits another class.
The target method is Resources.UnloadUnusedAssets(), which is an unmanaged internal call
The game is running on Unity version 5.6.2.

MonoMod.RuntimeDetour version 18.10.22.8 is reported to work in this situation however, the ones after (not actually sure if 18.10.22.8 was the last working version, it's just a random one that does) crash with this exception:

Stack trace:

[Error] NullReferenceException: Object reference not set to an instance of an object
[Error] Stack trace:
MonoMod.RuntimeDetour.Platforms.DetourRuntimeILPlatform..ctor ()
MonoMod.RuntimeDetour.Platforms.DetourRuntimeMonoPlatform..ctor ()
MonoMod.RuntimeDetour.DetourHelper.get_Runtime ()
MonoMod.RuntimeDetour.NativeDetour..ctor (System.Reflection.MethodBase from, System.Reflection.MethodBase to)
KK_Fix_ResourceUnloadOptimizations.ResourceUnloadOptimizations.Awake ()
UnityEngine.GameObject:AddComponent(Type)
BepInEx.Bootstrap.Chainloader:Start()
BepInEx.Bootstrap.Linker:StartBepInEx()
BepInEx.Bootstrap.Entrypoint:Init()
UnityEngine.Application:.cctor()

Point of failure seems to be https://github.com/0x0ade/MonoMod/blob/master/MonoMod.RuntimeDetour/Platforms/Runtime/DetourRuntimeILPlatform.cs#L47

Removing this check results in:

{System.NullReferenceException: Object reference not set to an instance of an object
  at MonoMod.Utils.DynamicMethodDefinition.Generate (System.Object context) [0x00000] in <filename unknown>:0 
  at MonoMod.Utils.DynamicMethodDefinition.Generate () [0x00000] in <filename unknown>:0 
  at MonoMod.RuntimeDetour.Platforms.DetourRuntimeILPlatform.CreateCopy (System.Reflection.MethodBase method) [0x00000] in <filename unknown>:0 
  at MonoMod.RuntimeDetour.Platforms.DetourRuntimeILPlatform.TryCreateCopy (System.Reflection.MethodBase method, System.Reflection.MethodInfo& dm) [0x00000] in <filename unknown>:0 }

Example

Using a patch example of this:

			var detour = new NativeDetour(typeof(Resources).GetMethod(nameof(Resources.UnloadUnusedAssets)),
				targetMethod);

			detour.Apply();
			originalUnload = detour.GenerateTrampoline<Func<AsyncOperation>>();

This works:

    public static class Hooks
    {
	    public static Func<AsyncOperation> originalUnload;

	    public static AsyncOperation StackTraceUnload()
	    {
			Trace.WriteLine("UNLOAD CALL");
			Trace.WriteLine(Environment.StackTrace);

		    return originalUnload();
	    }
    }

This, however, does not:

    public class MyPlugin : BaseUnityPlugin
    {
	    public static Func<AsyncOperation> originalUnload;

	    public static AsyncOperation StackTraceUnload()
	    {
			Trace.WriteLine("UNLOAD CALL");
			Trace.WriteLine(Environment.StackTrace);

		    return originalUnload();
	    }
    }

EventDefinition / EventReference not taken into account

Right now, MonoMod practically ignores the existence of any EventDefinitions / EventReferences.

From Vike on the MonoMod server:

so I found that each event has an EventDefinition and a FieldDefinition so FullName isn't technically unique
they have the same FullName

Duplicate assembly references of differing versions

My target assembly has a reference to mscorlib 2.0.5.0 which I believe is some subset of the Unity version of mscorlib. I found a way to make my merging DLL to use that, but since MonoMod injects some types into the assembly, that assembly then gets a reference to the mscorlib used by MonoMod, which is mscorlib 2.0.0.0. This causes weird behavior in unity. So I then have to open up the assembly in dnspy and save it in order to get it to remove that extra reference.

The types copied from a source assembly should have the reference to mscorlib changed to whatever the target assembly's version is.

RuntimeDetour selftest failing on armv7, Android 4.X / 5.X

Thanks for your great job.I integrated the project to my Stardew Valley Mod Loader, and received some crash report on Android 5.1.1 and earlier version.
Here is the error log:
DetourRuntimeILPlatform._SelftestGetStruct (System.IntPtr x, System.IntPtr y)
System.Exception: This method should've been detoured!
screenshot

After updating to newer MonoMod version, MonoMod fails w/ SetPublic error

1>  Unhandled Exception: System.InvalidOperationException: MonoMod can't set metadata token providers of the type Mono.Cecil.EventDefinition public.
1>     at MonoMod.Utils.MonoModExt.SetPublic(IMetadataTokenProvider mtp, Boolean p) in D:\home\Documents\GitHub\MonoMod\MonoMod.Utils\MonoModExt.cs:line 704
1>     at MonoMod.MonoModder.PatchEvent(TypeDefinition targetType, EventDefinition srcEvent, HashSet`1 propMethods) in D:\home\Documents\GitHub\MonoMod\MonoMod\MonoModder.cs:line 1227
1>     at MonoMod.MonoModder.PatchType(TypeDefinition type) in D:\home\Documents\GitHub\MonoMod\MonoMod\MonoModder.cs:line 1086
1>     at MonoMod.MonoModder.PatchModule(ModuleDefinition mod) in D:\home\Documents\GitHub\MonoMod\MonoMod\MonoModder.cs:line 1041

The only thing I changed besides updating the MonoMod exe and dlls was the changing of MMILRT.Modder.ShouldCleanupAttrib = IsUselessAttrib; to MonoModRule.Modder.ShouldCleanupAttrib = IsUselessAttrib;

a little code issue

In MonoMod.RuntimeDetour.Hook.cs line 52-54.

if (target == null && !to.IsStatic) {
	throw new InvalidOperationException($"Hook for method {from} must be static, or you must pass a target instance.");
}

it check the "to" paramemter but the Exception message BUT throw the "from" paramemter, should be miswrote i think

Suppress MonoMod Added?

Is there a way to surpress the [MonoModAdded] attribute? (possibly for a class or even better a namespace?)

I have several classes that I'm adding to the assembly, but those are basically just a straight "copy" into the target assembly (under a namespace of "Modding"). I really I only need the added attribute for methods/classes that are done inside of one of the namespaces in the target assembly.

It's not a huge deal, it just clutters up the classes/methods with necessary fluff for stuff that I'm adding that is entirely new.

Unwanted behaviour caused by name conflict of compiler generated members

Description

If a method contains lambdas, compiler will generate a lambda method in <>c.<[methodName]>b__[methodOrdinal]_[lambdaOrdinal], and a cache field in <>c.<>9__[methodOrdinal]_[lambdaOrdinal]. Since the name of the cache field is only based on ordinals, if patch_[className] has the same cache field name as the original class, lambdas may not work as expected after patching.

MonoMod version: 21.1.11.1

Example

The entire project can be downloaded from here, including source code and output files.

Suppose we have ConflictTest/ConflictTest.cs, which is the original class:

using System;

namespace ConflictTest {
    internal class ConflictTest {
        private static void Test1() {
            Action func = () => Console.WriteLine("Test1");
            func();
        }

        private static void Test2() {
            Func<int> func = () => {
                Console.WriteLine("Test2");
                return 0;
            };
            func();
        }

        private static void Test3() {
            Console.WriteLine("Test3");
        }

        private static void Test4() {
            Console.WriteLine("Test4");
        }

        public static void Main(string[] args) {
            Console.WriteLine("=== Test1() ===");
            Test1();

            Console.WriteLine("=== Test2() ===");
            Test2();

            Console.WriteLine("=== Test3() ===");
            Test3();

            Console.WriteLine("=== Test4() ===");
            Test4();
        }
    }
}

and ConflictTest.Mod.mm/ConflictTest.cs, which is the patch that we are going to apply:

using System;
using MonoMod;

namespace ConflictTest {
    internal class patch_ConflictTest {
        [MonoModReplace]
        private static void Test3() {
            Action func = () => Console.WriteLine("patched Test3");
            func();
        }

        [MonoModReplace]
        private static void Test4() {
            Action func = () => Console.WriteLine("patched Test4");
            func();
        }
    }
}

After patching, the program is supposed to output:

=== Test1() ===
Test1
=== Test2() ===
Test2
=== Test3() ===
patched Test3
=== Test4() ===
patched Test4

But actually it outputs:

=== Test1() ===
Test1
=== Test2() ===
Test2
=== Test3() ===
Test1
=== Test4() ===

Unhandled Exception: System.MissingFieldException: Field not found: '<>c.<>9__1_0'.
   at ConflictTest.ConflictTest.Test4()
   at ConflictTest.ConflictTest.Main(String[] args)

Test3() should outputs patched Test3 but it outputs Test1, and Test4() should outputs patched Test4 but the program crashes.

If we put the code of original class into SharpLab (link), we can find that the lambda in Test1() became <>c.<Test1>b__0_0(), and in Test1(), the code first check for the cache field <>c.<>9__0_0, if it is null, then assign <>c.<Test1>b__0_0() to it and execute it.

If we put patch_ConflictTest into SharpLab (link), we can find that the cache field of the lambda in Test3() is also <>c.<>9__0_0, so these two fields conflict and when running the patched program, the cache field is assigned to the method that outputs Test1 when executing Test1(), and when executing Test3(), the cached field is used so the output is same as Test1(). As for Test2() and Test4(), the type of cache field is Func<int> in the original class and Action in patch and patched class, so I guess the casting can't be done and it crashes.

Putting placeholder members before the actual patch methods can solve this because the ordinal of them increase and no longer conflict with original ones.

*** ConflictTest.Mod.mm/ConflictTest.cs
@@ -4,8 +4,12 @@
 namespace ConflictTest {
     internal class patch_ConflictTest {
+        public string PlaceHolder1;
+        public string PlaceHolder2;
+        public string PlaceHolder3;
+        public string PlaceHolder4;

         [MonoModReplace]
         private static void Test3() {
             Action func = () => Console.WriteLine("patched Test3");
             func();
         }

Reference: The pattern of compiler generated names: GeneratedNames.cs and GeneratedNameKind.cs

Assemblies are not Signed

Description

The assemblies are not signed and can not be referenced from a signed project.
That's criminal negligence by anybody that creates assemblies used by others, given how trivial it is to give an assembly a strong name while building it. Doing it afterwards is quite painful, you have to decompile the assembly with ildasm.exe and put it back together with ilasm.exe, now using the /key option.

The code doesn't have any comments

Thank you for the tools, but I cannot understand their meaning and usage. Because all classes, methods and members are not commented.

DMD tests fail on some targets

From log of build 216:

2019-02-07T14:38:53.9276265Z Results File: D:\a\_temp\VssAdministrator_fv-az576_2019-02-07_14_38_53.trx
2019-02-07T14:38:53.9284439Z 
2019-02-07T14:38:53.9286042Z Total tests: 7. Passed: 7. Failed: 0. Skipped: 0.
2019-02-07T14:38:53.9286274Z Test Run Successful.
2019-02-07T14:38:53.9286489Z Test execution time: 8.2340 Seconds
2019-02-07T14:38:53.9977187Z ##[error]Error: C:\hostedtoolcache\windows\dncs\2.0.0\x64\dotnet.exe failed with return code: 1
2019-02-07T14:38:55.6017726Z ##[error]Dotnet command failed with non-zero exit code on the following projects : D:\a\1\s\MonoMod.UnitTest\MonoMod.UnitTest.csproj

`patch_` class doesn't get relinked when used in argument of an attribute

Description

If a patch_ class is used in the System.Type argument of an attribute, it will not be relinked to the actual class after patching.

MonoMod version: 21.8.19.1

Example

Main project, compiles to ConsoleApp.exe:

using System;
using System.Linq;
using System.Reflection;
using System.Security.Permissions;

namespace ConsoleApp {
    public class TestAttribute : Attribute {
        public Type Type { get; set; }

        public TestAttribute(Type type) {
            Type = type;
        }
    }

    public class PatchClass {
        public static void TestMethod() {
        }
    }

    public static class Program {
        public static void Main(string[] args) {
            Type type = typeof(PatchClass).GetMethod("TestMethod")
                .CustomAttributes
                .First(attr => attr.AttributeType == typeof(TestAttribute))
                .ConstructorArguments[0]
                .Value as Type;
            Console.WriteLine(type.FullName);
        }
    }
}

Patcher project, compiles to ConsoleApp.Mod.mm.dll:

using System;
using MonoMod;

namespace ConsoleApp {
    public class patch_PatchClass : PatchClass {
        [MonoModReplace]
        [Test(typeof(patch_PatchClass))]
        public new static void TestMethod() {
        }
    }
}

Run MonoMod.exe ConsoleApp.exe in command line, and open MONOMODDED_ConsoleApp.exe, it should outputs ConsoleApp.PatchClass, but it throws this exception instead:

Unhandled Exception: System.TypeLoadException: Could not load type 'ConsoleApp.patch_PatchClass' from assembly 'ConsoleApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
   at System.RuntimeTypeHandle.GetTypeByNameUsingCARules(String name, RuntimeModule scope, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.GetTypeByNameUsingCARules(String name, RuntimeModule scope)
   at System.Reflection.CustomAttributeTypedArgument.ResolveType(RuntimeModule scope, String typeName)
   at System.Reflection.CustomAttributeTypedArgument..ctor(RuntimeModule scope, CustomAttributeEncodedArgument encodedArg)
   at System.Reflection.CustomAttributeData.get_ConstructorArguments()
   at ConsoleApp.Program.Main(String[] args)

Hook on methods with struct parameters garble the struct

Description

Using v19.11.05.01 and Runtimedetour for On.etc hooks, applying a hook on a method which has a struct as one of its parameters causes subsequent orig(,..., struct,...) calls to use a struct which seems garbled. The struct in the hook delegate itself will behave normally.

Example

//Original Code:
public struct MyStruct
{
    bool myBool;
    string myString;
}
public static void PrintConditionalStruct(MyStruct parameter)
{
    if(parameter.myBool){
        Debug.Log(myString);
    }
}
//Calling code:
var displayThis = new myStruct { true, "WORD This should be displayed!" };
PrintConditionalStruct(displayThis);
// The hook:
On.PrintConditionalStruct += (orig, param) =>
{
    if(param.myBool && param.myString.StartsWith("WORD"){
        Debug.Log("Replaced!");
        param.myString = param.myString.Substring(5);
        }
    orig(param);
}

Then the expected result would be:
Replaced!
This should be displayed!
However, currently I expect this to display just Replaced! instead.

We've encountered this issue in various places when modding risk of rain 2
In code Examples are RoR2.Chat.CCSay, RoR2.InteractableSpawnCard.DoSpawn

Fix references in documentation using <see> tags

While reading the code to understand how to use this (or related) library, I found following comment in MonoMod.RuntimeDetour/NativeDetour.cs:

/// If you don't need the trampoline generator or any of the management helpers, use DetourManager.Native directly.

I didn't find the DetourManager and I think this was meant to be DetourHelper. If so, correcting this would make everything more understandable.

Overwrite private methods and insert code between lines

Hi!
So far I've been able to detour methods without using RuntimeDetours that I would like not to use.
Is it possible to inject code between the lines of a method and how can you overwrite a private method of a class being patched?

Or is all/most of this only possible with RuntimeDetours?
If so, can you somehow inject code (not IL instructions) at a specific point (for instance a defined IL location)/line?

How to branch inside method?

Trying to inject a branch into some drawing code.

if (cursor.TryGotoNext(i => i.MatchLdcI4(1),
                       i => i.MatchLdcI4(1),
                       i => i.MatchCallvirt<OverlayManager>("Draw")))
{
    cursor.Index++;
    var jumpTo = cursor.Body.Instructions[cursor.Index + 12];
    cursor.Emit(OpCodes.Ldc_I4_0);
    cursor.Emit(OpCodes.Brfalse_S, jumpTo);
}

This isn't the actual branch I'm trying to do. Just thought I'd try a super simple short one in the the area I'm trying to modify. I tried a few different branch opcodes and areas to branch to. Keep getting this.
image
JIT Compiler encountered an internal limitation.

MonoModOriginalName being added to the orig_Method

If you have a setup like:

public void orig_MyMethod(){ }

public void MyMethod() {
//do stuff
orig_MyMethod()
}

MonoMod adds [MonoModOriginalName] on the orig_MyMethod but does so without the ("MyMethod") constructor on the attribute. This is syntactically invalid and if you try to edit the resulting assembly with something like dnspy, you can't compile.

I fixed this in the monomod code using:

MonoModder.cs:1331

                // Fix MonoModOriginalName should not be put onto the original methods as it would add them without the argument.
                List<CustomAttribute> toRemove = origMethod.CustomAttributes.Where(x => x.AttributeType.Name == "MonoModOriginalName").ToList();
                
                foreach (CustomAttribute attrib in toRemove)
                    origMethod.CustomAttributes.Remove(attrib);

Platform is global and shouldn't be

Having issues with the fact that the Platform enum is in the global namespace. Is there any good reason it can't be in the MonoMod Namespace?

HarmonyDetourBridge.Init Failed on Android 6

Description

Here is a bug reported by a user of my mod loader.
Looks like it was failed when calling HarmonyDetourBridge.Init

OS Version: Android 6.0.1
Device Name: Huawei Honor 5X KIW-L21C10B370

Error log

System.ComponentModel.Win32Exception (0x80004005): Success
  at MonoMod.RuntimeDetour.Platforms.DetourNativeMonoPlatform.SetMemPerms (System.IntPtr start, System.UInt64 len, MonoMod.RuntimeDetour.Platforms.DetourNativeMonoPlatform+MmapProts prot) [0x00053] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Platforms.DetourNativeMonoPlatform.MakeExecutable (System.IntPtr src, System.UInt32 size) [0x00001] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Platforms.DetourNativeARMPlatform.FlushICache (System.IntPtr src, System.UInt32 size) [0x00040] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Platforms.DetourNativeMonoPlatform.FlushICache (System.IntPtr src, System.UInt32 size) [0x00001] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.DetourHelper.FlushICache (MonoMod.RuntimeDetour.IDetourNativePlatform plat, MonoMod.RuntimeDetour.NativeDetourData detour) [0x00000] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Platforms.DetourRuntimeILPlatform..ctor () [0x0009d] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Platforms.DetourRuntimeMonoPlatform..ctor () [0x00000] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.DetourHelper.get_Runtime () [0x0003e] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.DetourHelper.Pin[T] (T method) [0x00001] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Hook..ctor (System.Reflection.MethodBase from, System.Reflection.MethodInfo to, System.Object target) [0x0037e] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.Hook..ctor (System.Reflection.MethodBase from, System.Reflection.MethodInfo to) [0x00000] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at MonoMod.RuntimeDetour.HarmonyDetourBridge.Init (System.Boolean forceLoad, MonoMod.RuntimeDetour.HarmonyDetourBridge+Type type) [0x0011f] in <5bec6a1f632c4993806e737ce3655fb3>:0
  at StardewModdingAPI.Framework.SCore.RunInteractively () [0x0017f] in <5bec6a1f632c4993806e737ce3655fb3>:0

Occasional RuntimeDetour memory corruption

I don't know what even remotely causes this. When using RuntimeDetour to hook method A any method, it's possible to break another unrelated method B. Given the same input, it's always the same method B, which means that the corruption is deterministic. this is hell on earth.

MonoModReplace not working properly

Discord DM with @bluecheetah001:

I intend to use MonoModReplace in 4 spots at the moment in https://github.com/bluecheetah001/FEZ_TAS

but it seems to only work correctly in 1

in Mod_FezEngine/FezEngine/Services/KeyboardStateManager, there are 2 MonoModReplace that when uncommented cause a type load error because the methods are not implemented

in Mod_FezEngine/FezEngine/Components/InputManager when uncommenting MonoModReplace does not cause any load error, but it seems to just never call the modded Update method

in Mod_FEZ/FezGame/Program, MonoModReplace works correctly on the main method

Generic class patch issue

I made a patch for a generic method, but it does not works properly.
It looks like the MonoMod makes the generic patch applied to all of the class no matter what generic parameter is.

Here is the stacktrace:

System.ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array.
  at (wrapper stelemref) System.Object.virt_stelemref_class(intptr,object)
  at System.Collections.Generic.List`1[T].AddWithResize (T item) [0x00019] in <d4a23bbd2f544c30a48c44dd622ce09f>:0 
  at System.Collections.Generic.List`1[T].Add (T item) [0x00034] in <d4a23bbd2f544c30a48c44dd622ce09f>:0 
  at Netcode.NetArray`2[T,TField].Add (T item) [0x00025] in <669e457a4d0e4e69b6cd704e0c016001>:0 
  at Netcode.NetObjectShrinkList`1[T].Add (T item) [0x00000] in <669e457a4d0e4e69b6cd704e0c016001>:0 
  at StardewValley.Debris.init (System.Int32 debrisType, System.Int32 numberOfChunks, Microsoft.Xna.Framework.Vector2 debrisOrigin, Microsoft.Xna.Framework.Vector2 playerPosition, System.Single velocityMultiplyer) [0x0034f] in <669e457a4d0e4e69b6cd704e0c016001>:0 

My patch code:

    internal class NetArrayPatch<T, TField> : IHarmonyPatch where TField : NetField<T, TField>, new()
    {
        public static NetArrayPatch<T, TField> Instance { get; private set; } = null;

        public delegate void FieldCreateEvent(NetArray<T, TField> __instance, int index, TField field);

        public event FieldCreateEvent OnFieldCreate;

        public NetArrayPatch()
        {
            Instance = this;
        }

        public void Apply(HarmonyInstance harmony)
        {
            harmony.Patch(
                original: AccessTools.Method(typeof(NetArray<T, TField>), "createField"),
                postfix: new HarmonyMethod(typeof(NetArrayPatch<T, TField>), nameof(NetArrayPatch<T, TField>.After_createField))
            );
        }

        private static void After_createField(NetArray<T, TField> __instance, int index, ref TField __result)
        {
            Instance.OnFieldCreate?.Invoke(__instance, index, __result);
        }
    }

    internal class NetListWatcher<TValue> : BaseDisposableWatcher, ICollectionWatcher<TValue>
        where TValue : class, INetObject<INetSerializable>
    {
         private readonly NetList<TValue, NetRef<TValue>> Field;
        private static readonly Harmony.HarmonyInstance _harmonyInstance = Harmony.HarmonyInstance.Create("SMAPI.NetListWatcher");
        public NetListWatcher(NetList<TValue, NetRef<TValue>> field)
        {
            this.Field = field;
            if(NetArrayPatch<TValue, NetRef<TValue>>.Instance == null)
            {
                new NetArrayPatch<TValue, NetRef<TValue>>().Apply(_harmonyInstance);
            }
            this.innerArray = (NetRef<NetArray<TValue, NetRef<TValue>>>)this.Field.GetType().GetField("array", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(this.Field);
            NetArrayPatch<TValue, NetRef<TValue>>.Instance.OnFieldCreate += this.hookField;
        }
        private void hookField(NetArray<TValue, NetRef<TValue>> __instance, int index, NetRef<TValue> field)
        {
        }
    }

Generic method creation

I'm new to MonoMod and I've come here by backtracking the issue of patching generic methods in Harmony, so forgive me if I'm overlooking something. I was looking at the DynamicMethodDefinition to see how the methods are created, and if I'm reading this correctly the methods generated are always specific ones.
https://github.com/MonoMod/MonoMod.Common/blob/acfe156306ef8a47630660345013fc222ccf8657/Utils/DynamicMethodDefinition.cs#L100-L125
So my question is if we add an optional Collection<string> parameter to generate Collection<GenericParameters>, then use:

def.GenericParameters.Addrange(...)

would that be enough for generating the generic method? I have used this issue as an inspiration.

And a related issue that brought me here. If the passed Type to module.ImportReference() is a generic type I eventually get a System.NotSupportedException in MonoMod.Utils.MMReflectionImporter.ImportGenericParameter, I suspect due to not passing a IGenericParameterProvider to Mono.Cecil.ModuleDefinition.ImportReference. This problem would be similarly resolved if the generic type is detected and the MethodInfo or other relevant IGenericParameterProvider is passed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.