Сборка с msbuild и динамично ссылками проекта набора

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

public interface ISnaphot<T>
{
    T TakeSnapshot();
}

public class Immutable<T> where T : ISnaphot<T>
{
    private readonly T _item;
    public T Copy { get { return _item.TakeSnapshot(); } }

    public Immutable(T item)
    {
        _item = item.TakeSnapshot();
    }
}

Этот интерфейс был бы реализован примерно так:

public class Customer : ISnaphot<Customer>
{
    public string Name { get; set; }
    private List<string> _creditCardNumbers = new List<string>();
    public List<string> CreditCardNumbers { get { return _creditCardNumbers; } set { _creditCardNumbers = value; } }

    public Customer TakeSnapshot()
    {
        return new Customer() { Name = this.Name, CreditCardNumbers = new List<string>(this.CreditCardNumbers) };
    }
}

И клиентский код будет выглядеть примерно так:

    public void Example()
    {
        var myCustomer = new Customer() { Name = "Erik";}
        var myImmutableCustomer = new Immutable<Customer>(myCustomer);
        myCustomer.Name = null;
        myCustomer.CreditCardNumbers = null;

        //These guys do not throw exceptions
        Console.WriteLine(myImmutableCustomer.Copy.Name.Length);
        Console.WriteLine("Credit card count: " + myImmutableCustomer.Copy.CreditCardNumbers.Count);
    }

Очевидный недостаток заключается в том, что реализация хороша только как клиент реализации ISnapshot TakeSnapshot, но на по крайней мере, это будет стандартизировать вещи, и вы будете знать, где искать, если у вас есть проблемы, связанные с сомнительной изменчивостью. Бремя также будет лежать на потенциальных разработчиках, чтобы понять, могут ли они обеспечить неизменность снимка и не реализовать интерфейс, если нет (то есть класс возвращает ссылку на поле, которое не поддерживает какой-либо вид клонирования / копирования и, следовательно, не может быть снимок-е изд.)

1112 Как я уже сказал, это начало - как я бы, наверное, начал - конечно, не оптимальное решение или законченная, отточенная идея. Отсюда я посмотрю, как изменилось мое использование, и соответственно изменил этот подход. Но, по крайней мере, здесь я бы знал, что я мог бы определить, как сделать что-то неизменное, и написать модульные тесты, чтобы убедиться, что это так.

Я понимаю, что это не так уж далеко от простой реализации объектной копии, но она стандартизирует копию с точки зрения неизменности. В кодовой базе вы можете увидеть некоторых разработчиков из ICloneable, некоторых конструкторов копирования и некоторые явные методы копирования, возможно, даже в одном классе. Определив что-то вроде этого, вы узнаете, что намерение определенно связано с неизменяемостью - я хочу сделать снимок, а не дублирующий объект, потому что мне нужно больше и этого объекта. Класс Immtuable<T> также централизует связь между неизменяемостью и копиями; если позже вы захотите как-то оптимизировать, например, кэшировать снимок до «грязного», вам не нужно делать это во всех разработчиках логики копирования.

8
задан Darren Gosbell 13 May 2009 в 11:16
поделиться

2 ответа

В поисках решения той же проблемы, с которой вы столкнулись, я пришел к предлагаемому решению, заключающемуся в наличии условия в ItemGroup. Но это имело побочный эффект, потому что в ссылках Visual Studio я мог видеть обе ссылки, что также повлияло на ReSharper.

Наконец, я использую «Выбрать, когда в противном случае», и у меня больше нет проблем с ReSharper и Visual Studio, показывающими две ссылки.

<Choose>
  <When Condition=" '$(Configuration)' == 'client1DeployClickOnce' ">
    <ItemGroup>
        <ProjectReferenceInclude="..\client1\app.Controls\app.Controls.csproj">
        <Project>{A7714633-66D7-4099-A255-5A911DB7BED8}</Project>
        <Name>app.Controls %28Sources\client1\app.Controls%29</Name>
      </ProjectReference>
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <ProjectReference Include="..\app.Controls\app.Controls.csproj">
        <Project>{2E6D4065-E042-44B9-A569-FA1C36F1BDCE}</Project>
        <Name>app.Controls %28Sources\app.Controls%29</Name>
      </ProjectReference>
    </ItemGroup>
  </Otherwise>
</Choose>

Вы можете прочитать об этом больше в моем сообщении в блоге: ProjectReference with Condition в файле проекта MSBuild

17
ответ дан 5 December 2019 в 07:36
поделиться

Каждый элемент MSBuild ( нормально, почти каждый ) может иметь связанное с ним Условие . Я бы посоветовал вам отредактировать файл проекта (который сам является файлом MSBuild) и поместить все ссылки на SQL-сервер в ItemGroup, для которой есть условие, например:

  <ItemGroup Condition="'$(SqlServerTargetEdition)'=='2005'">
    <!-- SQL Server 2005 References here -->
    <Reference Include="..."/>
  </ItemGroup>

И еще одна ItemGroup для Sql server 2008:

  <ItemGroup Condition="'$(SqlServerTargetEdition)'=='2008'">
    <!-- SQL Server 2008 References here -->
    <Reference Include="..."/>
  </ItemGroup>

Вы должны предоставить значение по умолчанию для свойства SqlServerTargetEdition, прежде чем эти элементы будут объявлены. Затем в командной строке вы можете переопределить это значение с помощью переключателя / p при вызове msbuild.exe .

Саид Ибрагим Хашими

Моя книга: Внутри Microsoft Build Engine: Использование MSBuild и Team Foundation Build

5
ответ дан 5 December 2019 в 07:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: