Search code examples
c#system.reflectionactivator

Activator failing to create an object instance, throwing MissingMethodException


Some code:

BinaryReader reader;

//...

JournalEntry.Instantiate((JournalEntry.JournalEntryType)reader.ReadByte(), reader)

JournalEntry:

public enum JournalEntryType {
    Invalid,
    Tip,
    Death,
    Level,
    Friend
}

private readonly static Dictionary<JournalEntryType, Type> instantiationBindings = new Dictionary<JournalEntryType, Type>() {
    {JournalEntryType.Invalid, typeof(JournalEntryOther)},
    {JournalEntryType.Tip, typeof(JournalEntryTip)},
    {JournalEntryType.Death, typeof(JournalEntryOther)},
    {JournalEntryType.Level, typeof(JournalEntryOther)},
    {JournalEntryType.Friend, typeof(JournalEntryOther)}
};

internal JournalEntry(BinaryReader reader) {
    Read(reader);
}

internal static JournalEntry Instantiate(JournalEntryType type, BinaryReader reader) {
    return (JournalEntry)Activator.CreateInstance(instantiationBindings[type], reader);;
}

JournalEntryTip:

internal JournalEntryTip(BinaryReader reader) {
    Read(reader);
}

The code at the very top is invoked with a byte of value 1, mapped to JournalEntryType.Tip.

When I try to run this code, it throws System.MissingMethodException: 'Constructor on type 'JournalEntryTip' not found.'

Why is that? The constructor exists and should be invoked with the right argument.


Solution

  • Because the constructor is internal, you need to jump through a few hoops to call it. So you either make it public if you can, or another method would be to invoke the constructor like this:

    // First get the relevant constructor
    var constructor = instantiationBindings[type]
        .GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, //Allow for internal ctors
            null,
            new[] { typeof(BinaryReader) }, // And the ctor takes a BinaryReader
            null);
    
    // Invoke the constructor
    return (JournalEntry)constructor.Invoke(new[] { reader});