Трябва ли сглобките да бъдат физически файлове? - WepAPI

Имаме потребителски интерфейс на MVC, който генерично ще се изчертава въз основа на типове данни, които получава от WebAPI. При стартиране на приложението на потребителския интерфейс извиквам моя WebApi, за да изтегля „LeadTypes“ надолу в списък със списък с асембли, използвайки двоичен формататор за сериализиране и десериализиране. Проблемът е, че когато препратките се премахнат от потребителския интерфейс, десериализаторът избухва и казва, че не може да намери InstallmentLoan, версия 1.0.0.0 или една от неговите зависимости. Е, няма други зависимости освен системата, това са само основни модели с персонализирани анотации на данни и т.н. Целта е да нямаме нито един от нашите типове, споменат в потребителския интерфейс.

Грешка „Не може да се зареди файл или сборка „LeadGenFramework.Entity.LeadType.InstallmentLoan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null“ или една от неговите зависимости. Системата не може да намери посочения файл.“

Трябва да има умен начин за използване и препращане в модулите на паметта, без да имате физическия файл. Това, което не разбирам, е защо търси файл, ако го имам в паметта?

Всякакви насоки биха били чудесни!

Ето FusionLog:

=== Информация за състоянието преди обвързване === LOG: DisplayName = LeadGenFramework.Entity.LeadType.InstallmentLoan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (Напълно посочен) LOG: Appbase = file:/// E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug LOG: Първоначален PrivatePath = NULL

Извикване на събрание: (Неизвестно)

LOG: Това обвързване започва в контекста на зареждане по подразбиране. LOG: Използване на конфигурационен файл на приложението: C:\Users\charbaugh\AppData\Local\Temp\tmp8271.tmp LOG: Използване на конфигурационен файл на хост: LOG: Използване на конфигурационен файл на машина от 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. LOG: Опит за изтегляне на нов URL файл:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType .InstallmentLoan.DLL. LOG: Опит за изтегляне на нов URL файл:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan.EXE. LOG: Опит за изтегляне на нов URL файл:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType .InstallmentLoan.EXE.


person chdev77    schedule 28.02.2014    source източник
comment
Как го имаш в паметта?   -  person Anton Tykhyy    schedule 01.03.2014
comment
просто използвайки основен поток, който се връща от Web API get.   -  person chdev77    schedule 01.03.2014
comment
Двоичната сериализация не включва никакви сборки в своя изход, а само техните пълни имена. Ако искате да десериализирате изхода, или трябва да имате сборките, където могат да бъдат заредени, или трябва да използвате фантастични техники за десериализация (сурогати и т.н.), за да десериализирате в обекти от различни типове.   -  person Anton Tykhyy    schedule 01.03.2014
comment
Антоне, това е маршрутът, по който вървя. Открих, че асемблиращият клас съдържа само основни свойства, а не действителните данни в асемблиращите файлове, метод, свойства и други.   -  person chdev77    schedule 01.03.2014


Отговори (2)


Ще трябва да вземете сглобките от някъде, за това ще трябва да предавате поточно съдържанието на сглобката и да извикате assembly.load(byte[] rawAssembly).

person Yishai Galatzer    schedule 01.03.2014
comment
Да, не мога да го накарам да работи. Но също така може да се окаже, че не сериализирам правилно от страна на webapi. - person chdev77; 02.03.2014
comment
Така че се опитвате да разберете отново - Опитвате ли се да сериализирате вашия действителен POCO тип асемблиране по кабела към клиента? Звучи като дупка в сигурността, която чака да бъде използвана. Разберете какви метаданни искате да предадете на клиента за описание на вашите типове и предайте само това, след което създайте това, от което се нуждаете, на клиента. Освен сигурността, предаването на модули води до много неща, които могат да се объркат (1. Липсващи зависимости, 2. Само C# клиенти, 3. Проблеми със съвместимостта на рамката) - person Yishai Galatzer; 03.03.2014
comment
Да, поко. Имам притеснението, което споменахте, но това е частен webapi. Знаейки какво правя сега, щях просто да сериализирам типовете... но също така имам нужда от достъп до персонализирани атрибути, анотации към данни и т.н. Благодаря. - person chdev77; 04.03.2014

Добре, разбрах това. Използвах отражения, за да получа сглобката и след това сериализирах типа сглобка. Сглобяването предоставя само информация за свойствата за сглобяването на физическия файл и не съдържа цяла графика на файла. Надявам се това да помогне на някого, научен урок!

Така че просто използвах това на контролера и след това реверсите на клиента.

    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);
        }
    }
}
person chdev77    schedule 02.03.2014