Как получить каталог приложения из моего приложения WPF во время разработки? - PullRequest
4 голосов
/ 27 ноября 2009

Как получить каталог приложения из моего приложения WPF, во время разработки? Мне нужно получить доступ к ресурсу в текущем каталоге моего приложения во время разработки, пока мой XAML отображается в конструкторе. Я не могу использовать решение, указанное в в этом вопросе , поскольку во время разработки и System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), и System.Reflection.Assembly.GetExecutingAssembly().Location указывают на местоположение IDE (Visual Studio ... Common7 или что-то в этом роде).

По запросу, чтобы уточнить мои цели: я хочу получить доступ к таблице базы данных во время разработки и отобразить графику этих данных. Проектирование выполняется в Visual Studio 2008, поэтому мне нужно очень конкретное решение очень специфической проблемы, а именно получение каталога сборки для моего приложения.

Ответы [ 5 ]

6 голосов
/ 21 января 2010

По вашему описанию кажется, что ваш код фактически выполняется в WPF Designer в Visual Studio, например, он является частью библиотеки пользовательских элементов управления, используемой для проектирования.

В этом случае Assembly.GetEntryAssembly() возвращает ноль, но следующий код получает путь к каталогу приложения:

  string applicationDirectory = (
    from assembly in AppDomain.CurrentDomain.GetAssemblies()
    where assembly.CodeBase.EndsWith(".exe")
    select System.IO.Path.GetDirectoryName(assembly.CodeBase.Replace("file:///", ""))
    ).FirstOrDefault();

Следующие шаги можно использовать для демонстрации этой работы в инструменте дизайнера WPF VS.NET 2008:

  1. Поместите этот код в проект "Библиотека пользовательских элементов управления WPF" или "Библиотека классов"
  2. Добавьте любой код, необходимый для чтения базы данных и возврата данных для отображения (в моем случае я просто вернул сам каталог приложения в виде строки)
  3. Ссылка на проект библиотеки из проекта, который вы разрабатываете
  4. Используйте пользовательские элементы управления или классы из файла XAML, чтобы заполнить ваш DataContext или иным образом предоставить данные для вашего пользовательского интерфейса (в моем случае я связал DataContext, используя x: Static)
  5. Отредактируйте этот XAML-файл с помощью «Windows Presentation Foundation Designer», что можно сделать, просто дважды щелкнув, если вы не изменили свой редактор по умолчанию, в этом случае используйте «Открыть с помощью ...»

Когда вы выполните эти шаги, объект, на который вы смотрите, будет заполняться данными из вашей базы данных одинаково как во время выполнения, так и во время разработки.

Существуют и другие сценарии, в которых эта же техника работает так же хорошо, и существуют другие решения, доступные в зависимости от ваших потребностей. Пожалуйста, дайте нам знать, если ваши потребности отличаются от тех, которые я предполагал выше. Например, если вы пишете надстройку VS.NET, вы находитесь в совершенно другой игре с мячом.

0 голосов
/ 05 июня 2017

Если вы интенсивно работаете над дизайнерами WPF, используя Adorner и т. Д., Используйте свойство / тип "Context"

подробности: - Во время разработки у вас есть экземпляр modelItem (я полагаю, вы это знаете), если нет, то вы можете создать его экземпляр в реализации переопределения метода Activate

// в классе DesignAdorner

public class DesignAdorner : PrimarySelectionAdornerProvider
{
      protected override void Activate(ModelItem item)
        {
                modelItem = item;
        }
}

Теперь вы можете получить доступ к текущему пути приложения, используя следующий однострочный код

string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName;

Дайте мне знать, если это вам не поможет.

0 голосов
/ 27 ноября 2009

Вы пытаетесь поддержать дизайнера (такого как дизайнер визуальной студии или Blend)?

Если это так, то существуют разные способы решения этой проблемы. Обычно вы не хотите полагаться на относительный путь от исполняемого файла, поскольку он может быть размещен в различных инструментах проектирования (VS, Expression Blend и т. Д.)

Может быть, вы можете более полно объяснить проблему, которую вы пытаетесь решить, чтобы мы могли дать лучший ответ?

0 голосов
/ 21 января 2010

Хорошо, учитывая дальнейшее разъяснение, вот что я буду делать.

В соответствии с заботой, выраженной GraemeF, делать то, что вы хотите, хрупко и в лучшем случае может сломаться.

Из-за этого общая практика состоит в том, чтобы рассматривать поддержку данных времени разработки как совершенно иной подход, чем поддержка данных времени выполнения. Проще говоря, связь, которую вы создаете между средой разработки и этой БД, является плохой идеей.

Чтобы просто предоставить данные времени разработки для визуализации, я предпочитаю использовать фиктивный класс, который придерживается общего интерфейса в качестве класса времени выполнения. Это дает мне возможность показать данные, которые, как я могу убедиться, имеют правильный тип и соответствуют тому же контракту, что и мой объект времени выполнения. Тем не менее, это совершенно другой класс, который используется для поддержки времени разработки (и часто используется для модульного тестирования).

Так, например. Если у меня был класс времени выполнения, в котором должны были быть указаны личные данные, такие как имя, фамилия и адрес электронной почты:

public class Person()
{
    public String FirstName { get; set;}
    public String LastName {get; set;}
    public Email EmailAddress {get; set;}
}

и я заполнял этот объект из БД во время выполнения, но мне также нужно было обеспечить визуализацию во время разработки. Я бы представил интерфейс IPerson, который определяет контракт, которому необходимо придерживаться, а именно обеспечивает существование методов получения свойств:

public interface IPerson()
{
    String FirstName { get; }
    String LastName { get; }
    Email EmailAddress { get; }
}

Затем я обновлю свой класс Person во время выполнения для реализации интерфейса:

public class Person() : IPerson
{
public String FirstName { get; set;}
public String LastName {get; set;}
public Email EmailAddress {get; set;}
}

Тогда я бы создал фиктивный класс, который реализует тот же интерфейс и предоставляет разумные значения для использования во время разработки

public MockPerson() : IPerson
{
public String FirstName { get { return "John"; } }
public String LastName { get { return "Smith"; } } 
public Email EmailAddress { get { return new Email("John@smith.com"); } }
}

Затем я бы реализовал механизм для предоставления объекта MockPerson во время разработки и реального объекта Person во время выполнения. Что-то вроде это или это . Это обеспечивает поддержку данных времени разработки без жесткой зависимости между средой выполнения и средой разработки.

Этот шаблон гораздо более гибок и позволит вам обеспечить согласованную поддержку данных времени разработки во всем приложении.

0 голосов
/ 27 ноября 2009

Я не думаю, что это возможно - вы спрашиваете место сборки, которая потенциально еще даже не была построена. Ваш код времени разработки не выполняется внутри вашего приложения и должен был бы сделать некоторые предположения относительно IDE. Мне это кажется неправильным и хрупким - подумайте над этими вопросами:

  • Проект уже построен?
  • Если нет, то нет исполняемого файла, чтобы получить путь, и что тогда?
  • Будут ли присутствовать другие файлы, если они не были собраны или они представляют собой артефакты?
  • Если он был построен, то где он был построен?
  • Нужно ли учитывать другие IDE?

В этой ситуации вам, вероятно, следует попросить пользователя во время разработки предоставить или просмотреть путь, добавив свойство вашего объекта для его редактирования. Ваш код времени проектирования может затем использовать значение свойства, чтобы найти то, что ему нужно.

...