Skip to content

Commit

Permalink
AccessTools.CreateInstance can now use non-public parameterless const…
Browse files Browse the repository at this point in the history
…ructors, define internal CodeInstruction parameterless constructor

AccessTools.CreateInstance also now invokes the ConstructorInfo rather than using Activator.CreateInstance; the former should be faster.
  • Loading branch information
lbmaian committed Nov 16, 2020
1 parent 2d4757a commit 66d7811
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 9 deletions.
13 changes: 9 additions & 4 deletions Harmony/Public/CodeInstruction.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
Expand All @@ -11,21 +11,26 @@ namespace HarmonyLib
public class CodeInstruction
{
/// <summary>The opcode</summary>
///
///
public OpCode opcode;

/// <summary>The operand</summary>
///
public object operand;

/// <summary>All labels defined on this instruction</summary>
///
///
public List<Label> labels = new List<Label>();

/// <summary>All exception block boundaries defined on this instruction</summary>
///
///
public List<ExceptionBlock> blocks = new List<ExceptionBlock>();

// Internal parameterless constructor that AccessTools.CreateInstance can use, ensuring that labels/blocks are initialized.
internal CodeInstruction()
{
}

/// <summary>Creates a new CodeInstruction with a given opcode and optional operand</summary>
/// <param name="opcode">The opcode</param>
/// <param name="operand">The operand</param>
Expand Down
5 changes: 3 additions & 2 deletions Harmony/Tools/AccessTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1692,9 +1692,10 @@ public static object CreateInstance(Type type)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
var ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[0], null);
var ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null,
CallingConventions.Any, new Type[0], modifiers: null);
if (ctor is object)
return Activator.CreateInstance(type);
return ctor.Invoke(null);
return FormatterServices.GetUninitializedObject(type);
}

Expand Down
6 changes: 3 additions & 3 deletions HarmonyTests/Tools/TestAccessTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,10 @@ public void Test_AccessTools_CreateInstance()
Assert.IsTrue(AccessTools.CreateInstance<AccessToolsCreateInstance.NoConstructor>().constructorCalled);
Assert.IsFalse(AccessTools.CreateInstance<AccessToolsCreateInstance.OnlyNonParameterlessConstructor>().constructorCalled);
Assert.IsTrue(AccessTools.CreateInstance<AccessToolsCreateInstance.PublicParameterlessConstructor>().constructorCalled);
Assert.IsFalse(AccessTools.CreateInstance<AccessToolsCreateInstance.InternalParameterlessConstructor>().constructorCalled);
Assert.IsTrue(AccessTools.CreateInstance<AccessToolsCreateInstance.InternalParameterlessConstructor>().constructorCalled);
var instruction = AccessTools.CreateInstance<CodeInstruction>();
Assert.Null(instruction.labels);
Assert.Null(instruction.blocks);
Assert.NotNull(instruction.labels);
Assert.NotNull(instruction.blocks);
}

[Test]
Expand Down

0 comments on commit 66d7811

Please sign in to comment.