我正在使用 CodeDomProvider 类来编译我正在开发的某个应用程序中的脚本。这些是我正在使用的3种方法。
public static void CompileNpcScripts(bool pLoadCompiledScripts)
{
Dictionary<string, DateTime> compiledScripts = new Dictionary<string, DateTime>();
foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\Compiled\\", "*.compiled"))
{
compiledScripts.Add(System.IO.Path.GetFileNameWithoutExtension(script), System.IO.File.GetLastWriteTime(script));
}
List<string> needCompliation = new List<string>();
foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\", "*.s"))
{
var shortname = System.IO.Path.GetFileNameWithoutExtension(script);
if (!compiledScripts.ContainsKey(shortname) || compiledScripts[shortname] < System.IO.File.GetLastWriteTime(script))
{
needCompliation.Add(script);
}
}
foreach (var script in needCompliation)
{
var shortname = System.IO.Path.GetFileNameWithoutExtension(script);
_usableNpcScripts.Remove(shortname);
CompilerResults results = CompileScript(ScriptType.Npc, script);
}
foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\Compiled\\", "*.compiled"))
{
var shortname = System.IO.Path.GetFileNameWithoutExtension(script);
if (!_usableNpcScripts.ContainsKey(shortname))
{
_usableNpcScripts.Add(shortname, Assembly.LoadFile(Environment.CurrentDirectory + "\\" + script));
}
}
if (pLoadCompiledScripts)
{
foreach (KeyValuePair<string, Assembly> script in _usableNpcScripts)
{
GameServer.NpcScripts.Add(script.Key, (INpcScript)ScriptingTools.FindInterface(script.Value, "INpcScript"));
}
}
else
{
foreach (var script in needCompliation)
{
var shortname = System.IO.Path.GetFileNameWithoutExtension(script);
if (GameServer.NpcScripts.ContainsKey(shortname))
{
GameServer.NpcScripts[shortname] = (INpcScript)ScriptingTools.FindInterface(_usableNpcScripts[shortname], "INpcScript");
}
}
}
}
public static CompilerResults CompileScript(ScriptType pType, string pSource)
{
try
{
if (_compiler == null)
{
_compiler = CodeDomProvider.CreateProvider("CSharp");
_compilerParams = new CompilerParameters();
_compilerParams.GenerateExecutable = false;
_compilerParams.CompilerOptions = "/optimize";
// TODO: Should it be generated in memory?
_compilerParams.GenerateInMemory = false;
_compilerParams.IncludeDebugInformation = false;
_compilerParams.ReferencedAssemblies.Add("System.dll");
_compilerParams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
{ }
int lol;
}
_compilerParams.OutputAssembly = "Scripts\\" + pType + "\\Compiled\\" + System.IO.Path.GetFileNameWithoutExtension(pSource) + ".compiled";
var result = _compiler.CompileAssemblyFromFile(_compilerParams, pSource);
if (System.IO.File.Exists(_compilerParams.OutputAssembly))
{
System.IO.File.SetLastWriteTime(_compilerParams.OutputAssembly, System.IO.File.GetLastWriteTime(pSource));
}
return result;
}
catch
{
// Stil being used by the user.
return null;
}
}
public static object FindInterface(Assembly pDLL, string pInterface)
{
foreach (Type type in pDLL.GetTypes())
{
if (type.GetInterface(pInterface, true) != null)
return pDLL.CreateInstance(type.FullName);
}
return null;
}
布尔“pLoadCompiledScripts”用于告诉程序脚本应该重新加载还是插入。 GameServer的NpcScripts dictionairy只是INpcScript接口的集合。
现在。在initla加载中,我调用以下内容:CompileNpcScripts(true),因此它将检查需要编译的文件,将重新编译它们,然后将所有这些文件加载到dictionairy中。我还有一个FileWatcher类,它监视Script文件夹中的更改。引发事件后,我调用CompileNpcScripts(false),因此它将重新加载现有脚本。但是,CompileScript方法返回null,因为另一个进程正在使用文件“[name] .compiled”。为什么我能这样解决它呢?感谢。
答案 0 :(得分:0)
问题可能是两件事之一。
首先,检查你的FileWatcher
课程并确保它没有抓住它正在观看的任何文件(比如访问上次修改日期属性或任何情况)。
其次,编译器在编译它们之后可能仍然保留脚本。我会尝试处理编译器并在每次重新编译脚本时重建它。