使用Fody时,CS-SCRIPT动态代码无法找到程序集

  • 使用Fody时,CS-SCRIPT动态代码无法找到程序集已关闭评论
  • 165 次浏览
  • A+
所属分类:.NET技术
摘要

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

}

}

}

@@#