程序集必须是物理文件吗? - Web API

时间:2014-02-28 22:54:39

标签: asp.net-web-api .net-assembly

我们有一个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。

2 个答案:

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