简体   繁体   English

如何写入运行时生成的 C# 中的 dll 文件?

[英]How to write to an at runtime generated .dll file in C#?

I have to change the contents of an.dll file at runtime, but cannot do so because it is in use and get a我必须在运行时更改 an.dll 文件的内容,但不能这样做,因为它正在使用中并获得

InvalidOperationException无效操作异常

instead.反而。

I am currently in the process of working out a way to compile C# code at runtime for a game made in Unity.我目前正在研究一种在运行时为 Unity 制作的游戏编译 C# 代码的方法。 Using the Microsoft.CSharp.CSharpCodeProvider and System.CodeDom.Compiler.CompilerParamters classes, I've got a system working that allows me to compile code and outputs it as a .dll file, so I can use it together with other classes.使用Microsoft.CSharp.CSharpCodeProviderSystem.CodeDom.Compiler.CompilerParamters类,我有一个系统工作,允许我编译代码并将其输出为.dll文件,因此我可以将它与其他类一起使用。 If you need to know more about the way I do this, take a look at the tutorial I used (and the below mentioned changes).如果您需要了解更多关于我这样做的方式,请查看我使用的教程(以及下面提到的更改)。

However, the compiling only works once, because the next time the compiler is run, the .dll file already exists and I get the following error message:但是,编译只工作一次,因为下次运行编译器时, .dll文件已经存在,我收到以下错误消息:

Could not write to file `fileName'.无法写入文件“fileName”。 Win32 IO returned 1224. Path: path/fileName.dll Win32 IO 返回 1224 路径:path/fileName.dll

These are the most important parts of my code:这些是我的代码中最重要的部分:

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);
}

I really don't want to give the file a different name every time, because that would make using it in other classes a pain.我真的不想每次都给文件一个不同的名字,因为那会让在其他类中使用它很痛苦。 I am assuming this can be solved by somehow telling the game that the old.dll file isn't in use anymore, because that shouldn't even be the case after the method has been excecuted, right?我假设这可以通过以某种方式告诉游戏 old.dll 文件不再使用来解决,因为在方法执行后甚至不应该是这种情况,对吧?

I am thankful for your answers!我很感谢你的回答!

As I said in the comments, I do this often with a twist.正如我在评论中所说,我经常这样做。 I have a calculus engine which compiles formulas.我有一个编译公式的微积分引擎。 Every time a formula changes, it's re compiled.每次公式更改时,都会重新编译。 Every time i need to run a formula, i instantiate its class.每次我需要运行一个公式时,我都会实例化它的 class。 But.... Every time I recompile, I create a NEW dll with a DIFFERENT name.但是....每次重新编译时,我都会创建一个具有不同名称的 NEW dll。 So I use a timestamp for the names and a timestamp for the class names.因此,我对名称使用时间戳,对 class 名称使用时间戳。 Everytime I instantiate, I look for the latest dll每次实例化时,我都会寻找最新的 dll

So my class inside the dll looks like:所以我的 dll 里面的 class 看起来像:

public class MyGeneratedClass_20191024103000 {
// do stuff
}

assembly creation (pseudocode):程序集创建(伪代码):

aseemblyManager.CreateLibrary(OUTPUT_DLLS_PATH + "\\Calculus_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".dll", refs, sourcecode) ... etc

aseembly load:组装负载:

string pathNewest = ListFolderSortByDate(); //you should also get the timestamp
assembly = Assembly.LoadFrom(pathNewest ); //register dll
mytype =  assembly.GetType("mycalculus"); 

finally, instantiation:最后,实例化:

 myobject= Activator.CreateInstance(mytype , new object[] { some parameters });
mytype .GetMethod("Calculate" + timestamp).Invoke(myobject, arrParam);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM