I'm working on a procedural asset generation system and I want it to be able to detect if the source file of a particular asset has changed so that it only has to regenerate assets that will actually be different.
Some googling has told me that there is no way to get the source file of a type using simple reflection, so I'm trying to come up with a workaround. Here's what I'm doing:
- Get a list of all .cs files in the project directory using Directory.GetFiles.
- Compile each file into its own assembly using CSharpCodeProvider.CompileAssemblyFromFile.
- If compiledAssembly.GetType(targetType.FullName) exists, then that is the source file of targetType.
The problem is that step 2 is giving compile errors without any sort of description:
- (0,0) : error :
- (0,0) : error : at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
- (0,0) : error : at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
- etc.
I think that this may be because the current assembly or app domain or whatever already contains the exact type it's trying to compile, but that's just a guess. Does anyone know what might be causing those errors or how I can avoid them?
Edit: here's the main code for step 2:
private static readonly CSharpCodeProvider CodeProvider = new CSharpCodeProvider();
private static readonly CompilerParameters CompilerOptions = new CompilerParameters();
static SourceInterpreter()
{
// We want a DLL in memory.
CompilerOptions.GenerateExecutable = false;
CompilerOptions.GenerateInMemory = true;
// Add references for UnityEngine and UnityEditor DLLs.
CompilerOptions.ReferencedAssemblies.Add(typeof(Application).Assembly.Location);
CompilerOptions.ReferencedAssemblies.Add(typeof(EditorApplication).Assembly.Location);
}
private static Assembly CompileCS(string filePath, out CompilerErrorCollection errors)
{
// Compile the assembly from the source script text.
CompilerResults result = CodeProvider.CompileAssemblyFromFile(CompilerOptions, filePath);
// Store any errors and warnings.
errors = result.Errors;
foreach (CompilerError e in errors)
{
if (!e.IsWarning) Debug.Log(e);
}
return result.CompiledAssembly;
}