如何在 C# 中写入运行时生成的 .dll 文件?
How to write to an at runtime generated .dll file in C#?
我必须在 运行 时更改 .dll 文件的内容,但不能这样做,因为它正在使用并得到
InvalidOperationException
相反。
我目前正在研究一种在 运行 时间为使用 Unity 制作的游戏编译 C# 代码的方法。使用 Microsoft.CSharp.CSharpCodeProvider
和 System.CodeDom.Compiler.CompilerParamters
类,我有一个系统可以编译代码并将其输出为 .dll
文件,因此我可以一起使用它们与其他 类。如果您需要了解更多关于我执行此操作的方式,请查看我使用的 the tutorial(以及下面提到的更改)。
然而,编译只工作一次,因为下一次编译器是运行,.dll
文件已经存在,我得到以下错误信息:
Could not write to file `fileName'. Win32 IO returned 1224. Path: path/fileName.dll
这些是我的代码中最重要的部分:
public void Compile() {
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
//...
parameters.GenerateInMemory = false; //generates actual file
parameters.GenerateExecutable = false; //generated .dll instead of .exe
//...
parameters.OutputAssembly = Application.dataPath + className + ".dll";
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
//...
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("GameLevel." + className);
MethodInfo excecuteMethod = program.GetMethod("Excecute");
excecuteMethod.Invoke(null, null);
}
我真的不想每次都给文件起一个不同的名字,因为那样会使在其他 类 中使用它很痛苦。我假设这可以通过以某种方式告诉游戏旧的 .dll 文件不再使用来解决,因为在执行该方法后甚至不应该是这种情况,对吗?
感谢您的回答!
正如我在评论中所说,我经常做这件事。
我有一个编译公式的微积分引擎。每次公式更改时,都会重新编译。
每次我需要 运行 一个公式时,我都会实例化它的 class。
但....
每次重新编译时,我都会创建一个名称不同的新 dll。
因此,我为名称使用时间戳,为 class 个名称使用时间戳。
每次实例化时,我都会寻找最新的 dll
所以我的 class 在 dll 中看起来像:
public class MyGeneratedClass_20191024103000 {
// do stuff
}
程序集创建(伪代码):
aseemblyManager.CreateLibrary(OUTPUT_DLLS_PATH + "\Calculus_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".dll", refs, sourcecode) ... etc
汇编加载:
string pathNewest = ListFolderSortByDate(); //you should also get the timestamp
assembly = Assembly.LoadFrom(pathNewest ); //register dll
mytype = assembly.GetType("mycalculus");
最后,实例化:
myobject= Activator.CreateInstance(mytype , new object[] { some parameters });
mytype .GetMethod("Calculate" + timestamp).Invoke(myobject, arrParam);
我必须在 运行 时更改 .dll 文件的内容,但不能这样做,因为它正在使用并得到
InvalidOperationException
相反。
我目前正在研究一种在 运行 时间为使用 Unity 制作的游戏编译 C# 代码的方法。使用 Microsoft.CSharp.CSharpCodeProvider
和 System.CodeDom.Compiler.CompilerParamters
类,我有一个系统可以编译代码并将其输出为 .dll
文件,因此我可以一起使用它们与其他 类。如果您需要了解更多关于我执行此操作的方式,请查看我使用的 the tutorial(以及下面提到的更改)。
然而,编译只工作一次,因为下一次编译器是运行,.dll
文件已经存在,我得到以下错误信息:
Could not write to file `fileName'. Win32 IO returned 1224. Path: path/fileName.dll
这些是我的代码中最重要的部分:
public void Compile() {
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
//...
parameters.GenerateInMemory = false; //generates actual file
parameters.GenerateExecutable = false; //generated .dll instead of .exe
//...
parameters.OutputAssembly = Application.dataPath + className + ".dll";
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
//...
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("GameLevel." + className);
MethodInfo excecuteMethod = program.GetMethod("Excecute");
excecuteMethod.Invoke(null, null);
}
我真的不想每次都给文件起一个不同的名字,因为那样会使在其他 类 中使用它很痛苦。我假设这可以通过以某种方式告诉游戏旧的 .dll 文件不再使用来解决,因为在执行该方法后甚至不应该是这种情况,对吗?
感谢您的回答!
正如我在评论中所说,我经常做这件事。 我有一个编译公式的微积分引擎。每次公式更改时,都会重新编译。 每次我需要 运行 一个公式时,我都会实例化它的 class。 但.... 每次重新编译时,我都会创建一个名称不同的新 dll。 因此,我为名称使用时间戳,为 class 个名称使用时间戳。 每次实例化时,我都会寻找最新的 dll
所以我的 class 在 dll 中看起来像:
public class MyGeneratedClass_20191024103000 {
// do stuff
}
程序集创建(伪代码):
aseemblyManager.CreateLibrary(OUTPUT_DLLS_PATH + "\Calculus_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".dll", refs, sourcecode) ... etc
汇编加载:
string pathNewest = ListFolderSortByDate(); //you should also get the timestamp
assembly = Assembly.LoadFrom(pathNewest ); //register dll
mytype = assembly.GetType("mycalculus");
最后,实例化:
myobject= Activator.CreateInstance(mytype , new object[] { some parameters });
mytype .GetMethod("Calculate" + timestamp).Invoke(myobject, arrParam);