I don’t understand what you are trying to achieve with your code. Are you trying to create C# code dynamically, that uses the Unity API while using reflection to invoke it?
Why don’t you try untying the guardian knot blindfolded with your teeth? That would be less complicated.
Any way, you seem to lack basic understanding of C# and generally statically strongly typed languages, the null reference is the least of your problems. Here are some problems with you code:
- You are using
GetComponent
on an instance of type object
, why do you think this would even compile? objects don’t have a GetComponent
method.
- You are trying to invoke a method in a type that doesn’t have that method.
src
type won’t neccesarily have the ‘MyMethod’
- You are passing a parameters object to a parameters array
- You have not instantiated the instance of the type that has the method
- What the method returns has to be cast back to the type you need
- You cannot use the code in the string without referencing the required assemblies that contain the definitions of the types you use
All that plus more, will make this code even if you managed to make it work, extremely slow as it creates a class, writes it to disk, compiles it, uses reflection and then deletes it.
Also would make it platform specific, os specific and compilation specific as the required assemblies would have to be binaries for the specific hardware,os and so on.
Also would make it very hard to debug, very hard to test plus would never be generic enough to run Unity specific commands.
I would suggest that you should try to learn some basic C# stuff first, like what is a strongly typed language, the differences between instances and types before trying something like this. Right now it is way out of your current level.
Anyway, this is the code that works with what (I think) you try to do:
public static object RunStringAsCode(string str, object src, params object[] parameters)
{
CSharpCodeProvider provider = new();
StringBuilder code = new StringBuilder();
code.Append(" using UnityEngine; \r\n");
code.Append(" using System; \r\n");
code.Append(" public class MyClass \r\n");
code.Append(" { \r\n");
code.Append(" public object MyMethod(GameObject param) \r\n");
code.Append(" { \r\n");
code.Append( str );
code.Append(" } \r\n");
code.Append(" } \r\n");
CompilerParameters compParams = new CompilerParameters();
compParams.ReferencedAssemblies.Add(@"C:\Program Files\Unity\Hub\Editor\6000.0.35f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll");
compParams.ReferencedAssemblies.Add(@"C:\Program Files\Unity\Hub\Editor\6000.0.35f1\Editor\Data\MonoBleedingEdge\lib\mono\4.8-api\Facades\netstandard.dll");
CompilerResults results = provider.CompileAssemblyFromSource(compParams, code.ToString());
Type classType = results.CompiledAssembly.GetType("MyClass");
System.Reflection.MethodInfo method = classType.GetMethod("MyMethod");
var instance = Activator.CreateInstance(classType);
return method?.Invoke(instance, parameters);
}
And it runs from a Monobehaviour
like this:
public class BehaviorReflection : MonoBehaviour
{
private readonly Type componentType = typeof(SpriteRenderer);
private SpriteRenderer sr;
private void Start()
{
var result = TestReflection.RunStringAsCode($"return (object)(param.GetComponent<{componentType}>());", this, gameObject);
sr = result as SpriteRenderer;
if(sr != null)
sr.color = Color.red;
}
}