我们有一个MVC UI,它将根据从WebAPI获取的数据类型一般绘制自己。在ui的应用程序启动时,我调用我的WebApi,使用二进制格式化程序在程序集列表中将“LeadTypes”拉下来进行序列化和反序列化。问题是,当从UI中删除引用时,反序列化程序会爆炸,说它无法找到InstallmentLoan,版本1.0.0.0或其依赖项之一。除了系统之外没有其他依赖项,这些只是带有自定义数据注释等的基本模型。目标是不在UI上引用任何类型。
错误“无法加载文件或程序集'LeadGenFramework.Entity.LeadType.InstallmentLoan,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其依赖项之一。系统找不到指定的文件。”< / p>
在没有物理文件的情况下,必须有一种聪明的方法在内存程序集中使用和引用。我不明白的是,如果我在内存中找到文件,为什么要找文件?
任何指针都会很棒!
这是FusionLog:
===预绑定状态信息=== 日志:DisplayName = LeadGenFramework.Entity.LeadType.InstallmentLoan,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null (完全指定的) 日志:Appbase = file:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug 日志:初始PrivatePath = NULL
日志:此绑定在默认加载上下文中启动。 日志:使用应用程序配置文件:C:\ Users \ charbaugh \ AppData \ Local \ Temp \ tmp8271.tmp 日志:使用主机配置文件: 日志:使用C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ config \ machine.config中的计算机配置文件。 日志:此时策略未应用于引用(私有,自定义,部分或基于位置的程序集绑定)。 日志:尝试下载新的URL文件:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan.DLL。 日志:尝试下载新的URL文件:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType .InstallmentLoan.DLL。 日志:尝试下载新的URL文件:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan.EXE。 日志:尝试下载新的URL文件:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType .InstallmentLoan.EXE。
答案 0 :(得分:0)
您必须从某处获取程序集,因为您需要流式传输程序集内容并调用assembly.load(byte [] rawAssembly)。
答案 1 :(得分:0)
好的,我想出来了。我使用反射来获取装配,然后序列化装配类型。程序集仅提供物理文件程序集的属性信息,它不包含文件的整个图形。 我希望这可以帮助某人,吸取教训!
所以我只是在控制器上使用它,然后在客户端上使用它。
public MemoryStream Get()
{
List<MemoryStream> leadTypeAssemblyStreams = new List<MemoryStream>();
foreach (string dllAssembly in _leadTypeNamespaces)
{
using (MemoryStream ms = new MemoryStream())
{
string filename = dllAssembly;
if (!filename.Contains(".dll"))
filename = filename + ".dll";
using (FileStream file = new FileStream(AssemblyDirectory + "\\" + filename, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
file.Close();
leadTypeAssemblyStreams.Add(ms);
ms.Close();
}
}
}
return new MemoryStream(SerializeObj(leadTypeAssemblyStreams));
}
internal static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
internal static byte[] SerializeObj(object obj)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
byte[] bytes = stream.ToArray();
stream.Close();
return bytes;
}
}
现在,我可以调用GetDeserializedFileStreamPaths(stream),它将返回从WebApi流式传输的文件的物理路径。这是我将参考的WebApiClient类。
public class LFGWebApiClientHelpers
{
public List<Type> GetLeadTypes(Stream stream)
{
List<string> assembliesFilePath = GetDeserializedFileStreamPaths(stream);
List<Assembly> assemblies = new List<Assembly>();
foreach (string filePath in assembliesFilePath)
{
assemblies.Add(Assembly.LoadFile(filePath));
}
List<Type> leadTypes = new List<Type>();
foreach (Assembly asm in assemblies)
{
Type leadType = asm.GetTypes().Where(x => x.GetCustomAttributes(typeof(WebApiExportedTypeAttribute), false).Length > 0).FirstOrDefault(x => x.Name.Contains("Lead"));
leadTypes.Add(leadType);
}
return leadTypes;
}
private static List<string> GetDeserializedFileStreamPaths(Stream stream)
{
try
{
List<string> assembliesPath = new List<string>();
IFormatter formatter = new BinaryFormatter();
List<MemoryStream> leadTypeAssemblyStreams = formatter.Deserialize(stream) as List<MemoryStream>;
int fileNumber = 1;
string leadTypeAsseblyDirectory = AssemblyDirectory.Replace("bin", "DownloadedLeadTypeAssemblies");
if (!Directory.Exists(leadTypeAsseblyDirectory))
Directory.CreateDirectory(leadTypeAsseblyDirectory);
try
{
if (leadTypeAssemblyStreams == null)
throw new Exception("Lead type assembly stream cannot be null.");
foreach (MemoryStream leadTypeAssemblyStream in leadTypeAssemblyStreams)
{
string localFileLocation = leadTypeAsseblyDirectory +
string.Format("\\LeadType{0}.dll", fileNumber);
//add path for return type
assembliesPath.Add(localFileLocation);
using (
FileStream file = new FileStream(localFileLocation, FileMode.Create, FileAccess.Write))
{
leadTypeAssemblyStream.WriteTo(file);
leadTypeAssemblyStream.Close();
}
fileNumber++;
}
}
catch (Exception ex)
{
throw new LGFException().SetMessage(ex);
}
stream.Close();
return assembliesPath;
}
catch (Exception ex)
{
throw new LGFException().SetMessage(ex, "There was a problems during the deserializtion of LeadTypes.");
}
}
private static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
}