October 11, 2009

Adding DataObjects.Net to .csproj: the new way

DataObjects.Net v4.1 offers a very simple way of adding it to DataObjects.Net. Let's take a look on typical .csproj file for it:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    ...
    <!-- Optional, default is false: -->
    <UsePostSharp>true</UsePostSharp>
    <!-- Required, see the description below: -->
    <DontImportPostSharp>true</DontImportPostSharp>
    <!-- Optional, default is false: -->
    <UseFiXml>true</UseFiXml>
    <!-- Optional, default is true: -->
    <CopyIndirectDependencies>false</CopyIndirectDependencies>
    <!-- Optional, default is environment variable value -->
    <DataObjectsDotNetPath>..\DO4</DataObjectsDotNetPath>
  </PropertyGroup>
  <ItemGroup>
    ...
    <Reference Include="PostSharp.Laos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL" />
    <Reference Include="PostSharp.Public, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL" />
    <Reference Include="Xtensive.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Core.Aspects, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Indexing, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Integrity, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Storage, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Storage.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Xtensive.Storage.All, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
  </ItemGroup>
  ...
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="$(DataObjectsDotNetPath)\Common\DataObjects.Net.targets" />
  ...
</Project>
Let's discuss each particular line here.

Properties:
  • UsePoshSharp property indicates whether PostSharp must be applied to this assembly. This option is necessary only for projects declaring persistent types (Entity, Structure or SessionBound descendants), but not for projects using them (in these cases it is optional).
  • DontImportPostSharp property indicates any separately installed PostSharp version (if any) must not be used. This is a required option - if you won't add corresponding line, your project won't compile on machine where PostSharp is installed with "Global PostSharp Auto-Detection" option. Installed version of PostSharp will detect indirect reference to it from any project that references DataObjects.Net assemblies (directly or indirectly), and will try to post-process its binary; but this is impossible, since now we don't install our weaver into your own PostSharp installation - it is integrated into PostSharp version we ship in Lib folder, that is used by DataObjects.Net.targets.
  • UseFiXml property turns on post-processing of XML comments for this project by FiXml tool. If you'd like to use <inheritdoc/> and <see ... copy="true"/> inside your documentation, just set it to true.
  • CopyIndirectDependencies ensures copying of all indirect dependencies to project output folder. This post describes why this is so convenient. Set it to false to disable this: default value of this property is true.
  • DataObjectsDotNetPath property may specify relative or absolute path to DataObjects.Net. If it is omitted (that's default case), value of the same environment variable will be used. This environment variable is defined by new Install.bat (and thus by installer as well). So now it is really easy to make your DataObjects.Net-based solution compilable after XCopy: either run <DataObjects.Net root folder>\Install\Install.bat on the target machine after XCopying, or specify relative path to DataObjects.Net root folder in .csproj/.vbproj with this option (this implies you must keep Common, Bin and Lib folders from  DataObjects.Net root folder inside your solution).
References:
  • To PostSharp.* assemblies. They're necessary only for assemblies containing persistent types, since our aspects are inherited from types declared there. As you see, there is no necessity to specify correct <HintPath> now: appropriate search path will be provided by DataObjects.Net.targets.
  • To Xtensive.* assemblies. They're necessary in almost any project using DataObjects.Net, since your own persistent types are inherited from types declared there. Again, there is no necessity to specify correct <HintPath> now: appropriate search path will be provided by DataObjects.Net.targets.
  • To Xtensive.Storage.All.dll. This assembly indirectly references all the assemblies that can be loaded by DataObjects.Net in any possible configuration. So for example, it indirectly references Mono.Security.dll, which is referenced by NPgSql.dll, which is loaded when DataObjects.Net is used with PostgreSQL provider. Referencing Xtensive.Storage.All.dll in conjunction with CopyIndirectDependencies option ensures output folder will contain all the assemblies necessary to run your application in any possible configuration.
Imports:
  • $(DataObjectsDotNetPath)\Common\DataObjects.Net.targets. This .targets file does all the magic that stands behind all the properties I just described. As you already know, its location depends on DataObjectsDotNetPath property value or the same environment variable.
New project template files contains these additional lines. If you're using Visual Basic .NET, the changes you should make to .vbproj file are absolutely the same.