Read-Only Fields

TL;DR: don't try to access injected readonly fields in static constructors or field initializers.

Injection attributes can be placed on readonly fields and getter-only auto properties to ensure that your other code can access the injected value without being able to change it. This can be very useful for preventing accidental reassignment, however it also creates the possibility for injection to fail if you attempt to access the member before its value is injected.

Mono - the framework Unity runs on - uses a Just In Time (JIT) compiler at runtime right before each piece of code is run the first time to see if there are any optimisations it can perform. This process greatly improves performance and generally doesn't interfere with anything, however in this case it can cause a problem since Weaver is exploiting unintended behaviour by using reflection to set readonly values which would normally give a compile error if you tried to set them outside a constructor.

If you access a static readonly field before its value has been injected (I.E. when the reference is still null) such as in a static constructor or field initializer, the JIT can see that you are accessing a field which is null, and since it "knows" the value of the field isn't allowed to change it can optimise your method to directly use null instead of getting the current value of the field every time it executes. This means that not only will the field be null the first time the method executes, but even after the field value is injected, that method will continue using null instead of the actual injected value until the application is closed.

Usually it's fairly easy to avoid accessing injected fields before they might be ready, but if you might need to do so you can simply use a property with a private setter or even simply a regular field.