2015-12-03 6 views
2

Контекста: В нашем приложении есть два отдельных библиотек DLL, которые хранилища переменных, сконфигурированные для различных типов аппаратных .Эти библиотек DLL имеет такое же имя и ссылки из нашего приложения, Теперь каждый раз, если мы хотим протестировать различный тип оборудования, мы должны скопировать соответствующую dll в место, где работает приложение. Я ищу обходной путь.несколько путей подсказки в csproj файл из текстового файл переменной

Ссылки: Я видел следующие темы,

1) .csproj multiple hint paths for an assembly

2) https://whathecode.wordpress.com/2012/10/07/conditional-project-or-library-reference-in-visual-studio/

Вопрос: Могу ли я объявить переменную в текстовом файле говорят <hardware> type1 </hardware> и импортируйте этот текстовый файл в файл csproj и назначьте соответствующий refe к моей заявке?

Любая помощь ..

Ниже тестовое приложение, которое дублирует наш проект. SignalPool1, SignalPool2 имеют одно и то же имя класса и являются хранилищами для двух разных конфигураций оборудования, доступных в двух разных местах нашего проекта. Если бы мы захотели протестировать аппаратное обеспечение1, мы удалили бы текущую ссылку и добавили бы ссылку пула сигналов, которая имеет отношение к тому же, что и для hardware2. Теперь, чтобы избежать этой ручной работы, я хотел автоматизировать этот процесс, чтобы объявить переменную в XML и получить доступ к переменной в файле csproj, чтобы решить, к кому обратиться во время компиляции/выполнения.

В настоящее время во избежание этой проблемы у меня есть отдельный exe, который читает xml и решает скопировать их в одну общую папку. Этот exe будет вызываться во время события prebuild в нашем проекте.

// Сигнал бассейн 1 Файл

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace SignalPool 
{ 
public abstract class SignalPool 
{ 
    public abstract string PreExec(); 
    public abstract string PostExec(); 
    public abstract string VnVExec(); 

    public static string HWVar1 = "HWVar1"; 
    public static string HWVar2 = "HWVar2"; 
    public static string HWVar3 = "HWVar3"; 
    public static string HWVar4 = "HWVar4"; 
} 

}

// Сигнал pool2

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 

    namespace SignalPool 
    { 
    public abstract class SignalPool 
    { 
    public abstract string PreExec(); 
    public abstract string PostExec(); 
    public abstract string VnVExec(); 

    public static string HWVar1 = "HWVar5"; 
    public static string HWVar2 = "HWVar6"; 
    public static string HWVar3 = "HWVar7"; 
    public static string HWVar4 = "HWVar8"; 
    } 
} 

// Доступ к бассейн Переменные

главного файла

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 

namespace TestLibraries 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 

     AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 

     Testhardware th = new Testhardware(); 
     th.functionToValues(); 



    } 

    private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     if (args.Name.Contains("SignalPool")) //Put in the name of your assembly 
     { 
      //var configValue = XDocument.Parse("<config><hardware>type1</hardware></config>").Document.Descendants("hardware").First().Value; 
      var configValue = XDocument.Load(@"C:\Users\ha23031\Documents\Visual Studio 2010\Projects\TestLibraries\TestLibraries\TestInfo.xml").Document.Descendants("IsRealHMI").First().Value; 
      if (configValue == "false") 
      { 
       return System.Reflection.Assembly.LoadFile(@"C:\Users\ha23031\Documents\Visual Studio 2010\Projects\TestLibraries\SignalPool\bin\Debug\SignalPool.dll"); 
      } 
      else if (configValue == "true") 
      { 
       return System.Reflection.Assembly.LoadFile(@"C:\Users\ha23031\Documents\Visual Studio 2010\Projects\SignalPool\bin\Debug\SignalPool.dll"); 
      } 
     } 
     return null; 
    } 


} 

}

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace TestLibraries 
{ 
    class Testhardware : SignalPool.SignalPool 
    { 
    public override string PostExec() 
    { 
     return string.Empty; 
    } 

    public override string PreExec() 
    { 
     return string.Empty; 
    } 

    public override string VnVExec() 
    { 
     return string.Empty; 
    } 

    public string functionToValues() 
    { 
     // This is how i access variables based on the loaded variables 
     string s = SignalPool.SignalPool.HWVar1; 
     return string.Empty; 
    } 
} 
} 
+1

Вы поднимаетесь в ту гору. Попробуйте вернуться к [Шаблон стратегии] (http://programmers.stackexchange.com/questions/285276/design-pattern-dll-per-strategy). –

+1

@TomBlodget, спасибо за ответ, я думаю, что я не сделал свое ясное. эти две DLL с одинаковым именем не являются частью нашего цикла разработки, которые поставляются нам двумя (аппаратными средствами типа 1, аппаратными средствами типа 2) различными командами. – ansar

+0

Для получения реального ответа вам необходимо определить свой * тест *. Запускает ли ваше приложение в отладчике или вы проводите тесты с ним? Ответ может быть таким же простым, как определение двух конфигураций сборки и установка соответствующих условий для вашей справки. – Filburt

ответ

0

Вам необходимо загрузить нужную DLL во время запуска приложения, прежде чем .Net загружает его для вас. NET будет загружать DLL по умолчанию, как только будет создан экземпляр этого класса. Поэтому перед доступом к свойствам обязательно загрузите соответствующую DLL. Убедитесь, что вы не получаете доступ к этим свойствам в начальном классе где-либо, поскольку .Net будет загружать его тогда.

Что-то вроде этого:

class Program 
{ 
    static void Main(string[] args) 
    { 
     //var configValue = XDocument.Parse("<config><hardware>type1</hardware></config>").Document.Descendants("hardware").First().Value; 
     var configValue = XDocument.Load("MyXmlConfig.xml").Document.Descendants("hardware").First().Value; 
     if (configValue == "type1") 
     { 
      System.Reflection.Assembly.LoadFile(@"C:\TEMP\MyAssembly_Type1.dll"); 
     } 
     else if (configValue == "type2") 
     { 
      System.Reflection.Assembly.LoadFile(@"C:\TEMP\MyAssembly_Type2.dll"); 
     } 

     MyRepositoryClass.Initialize(); 
    } 
} 

static class MyRepositoryClass 
{ 
    public static void Initialize() 
    { 
     var variable1 = MyAssembly.MyRepository.Variable1; 
     var variable2 = MyAssembly.MyRepository.Variable2; 
     var variable3 = MyAssembly.MyRepository.Variable3; 
    } 
} 

Alternative загружает DLL по требованию (когда.Net просит за него):

class Program 
{ 
    static void Main(string[] args) 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 

     MyRepositoryClass.Initialize(); 
    } 

    private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     if (args.Name.Contains("MyAssembly")) //Put in the name of your assembly 
     { 
      //var configValue = XDocument.Parse("<config><hardware>type1</hardware></config>").Document.Descendants("hardware").First().Value; 
      var configValue = XDocument.Load("MyXmlConfig.xml").Document.Descendants("hardware").First().Value; 
      if (configValue == "type1") 
      { 
       return System.Reflection.Assembly.LoadFile(@"C:\TEMP\MyAssembly_Type1.dll"); 
      } 
      else if (configValue == "type2") 
      { 
       return System.Reflection.Assembly.LoadFile(@"C:\TEMP\MyAssembly_Type2.dll"); 
      } 
     } 
     return null; 
    } 
} 
+0

привет, большое спасибо за ответ, я реализовал то же самое в своем приложении, но не работал, я думаю, что это потому, что он наследует некоторые из функций этого класса. Я отредактировал и добавил код в тестовое приложение. Пройдите код и сообщите мне, где я делаю ошибку. – ansar

+1

Вы объединили два разных способа сделать это. Во-первых, первая ручная загрузка не выполняется, потому что вы получаете доступ к свойствам в том же методе, что означает, что .Net уже загрузил стандартную DLL, прежде чем вы даже попытались загрузить ее. Во-вторых, вы забыли добавить обработчик событий, который на самом деле говорит .Net использовать функцию AssemblyResolve. Удалите часть ручной загрузки и используйте только часть AssemblyResolve. Не забудьте на самом деле прикрепить обработчик событий ... + = – Wolf5

+0

спасибо за наблюдение Обновлено еще не сработало. Я думаю, что это решение сборки будет выполняться только в том случае, если оно не разрешило dll во время выполнения, в моем случае я добавляю его только во время компиляции «Добавить ссылку» (поскольку существуют функции для наследования от этого класса), будет ли это вопрос? – ansar

1

«Могу ли я объявить переменную в текстовом файле сказать type1 и импортировать текстовый файл в моем файле csproj и назначить соответствующую ссылку на мое приложение?»

Разве это не exactly what I describe in the blog post you link to?

Посмотрите на определенной переменной «SomeProject» в файле конфигурации «ProjectReferences.txt» который я загружаю из файла .csproj.

ProjectReferences.txt

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup Condition="$(Configuration) == 'Debug With Project References'"> 
    <SomeProject>..\SomeProject</SomeProject> 
    </PropertyGroup> 
</Project> 

.csproj файл

<Import Project="..\ProjectReferences.txt" /> 
<Choose> 
    <When Condition="Exists($(SomeProject))"> 
    <ItemGroup> 
     <ProjectReference Include="$(SomeProject)\SomeProject.csproj"> 
     <Project>{6CA7AB2C-2D8D-422A-9FD4-2992BE62720A}</Project> 
     <Name>SomeProject</Name> 
     </ProjectReference> 
    </ItemGroup> 
    </When> 
    <Otherwise> 
    <ItemGroup> 
     <Reference Include="SomeProject"> 
     <HintPath>..\Libraries\SomeProject.dll</HintPath> 
     </Reference> 
    </ItemGroup> 
    </Otherwise> 
</Choose>