使用Fody時,CS-SCRIPT動態代碼無法找到程序集

FODY會將相關的程序集處理成資源文件,CS_SCRIPT強制要求引用的程序集必須是文件

@@@code

public override IEvaluator ReferenceAssembly(Assembly assembly)

{

if (assembly != null)//this check is needed when trying to load partial name assemblies that result in null

{

if (assembly.Location.IsEmpty())

throw new Exception(

$"Current version of CodeDom evaluator (csc.exe) doesn't support referencing assemblies " +

"which are not loaded from the file location.");

 

var asmFile = assembly.Location;

 

if (referencedAssemblies.FirstOrDefault(x => asmFile.SamePathAs(x)) == null)

referencedAssemblies.Add(asmFile);

}

return this;

}

@@#

 

解決辦法:

  1. 動態代碼涉及到的命名空間放在一個公共的程序集中,最好是接口描述,FODY生成的時候,將這個程序集排除在外
  2. 上述方法沒辦法做到發佈爲單一文件,畢竟使用FODY就是爲了只生成一個文件,可強行在代碼中在編譯動態代碼前,釋放該文件。(缺點:該程序集名稱固定在了代碼中)

@@@code

//fody時無法加載程序集,釋放到臨時文件使用(不在當前目錄下,防止釋放後不能刪除,下次程序啓動時優先從文件加載此程序集)

string protocolDll = FileHelper.GetAbsolutePath(Path.Combine("scripts", "Protocol.dll"));

AssemblyUtil.ExtractFodyDll(protocolDll, "protocol.dll");

//添加臨時目錄爲程序集搜索目錄

CSScript.GlobalSettings.AddSearchDir(Path.GetDirectoryName(protocolDll));

 

//動態執行代碼獲取所有數據

CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;

// // CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Roslyn;

//該方法與FODY衝突,FODY會導致無法找到引用

script = CSScript.Evaluator.ReferenceDomainAssemblies(DomainAssemblies.AllStaticNonGAC);

script.ReferenceAssembly(Path.GetFileName(protocolDll));//添加釋放出的程序集

 

 

public static void ExtractFodyDll(string fileName, string dllName)

{

System.Reflection.Assembly Asmb = System.Reflection.Assembly.GetCallingAssembly();

 

if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(fileName)))

System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(fileName));

string strName = "costura." + dllName;

using (System.IO.Stream ManifestStream = Asmb.GetManifestResourceStream(strName))

{

if (strName.EndsWith(".compressed"))

{

using (DeflateStream source = new DeflateStream(ManifestStream, CompressionMode.Decompress))

using (FileStream output = new FileStream(fileName, FileMode.Create))

source.CopyTo(output);

}

else

{

byte[] StreamData = new byte[ManifestStream.Length];

ManifestStream.Read(StreamData, 0, (int)ManifestStream.Length);

System.IO.File.WriteAllBytes(fileName, StreamData);

}

}

}

@@#

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章