MSBuild, персонализирана задача за стартиране на персонализиран инструмент за генериране на класове за linq to sql модел?

Имам следния сценарий. Използваме съхранени процедури за достъп до базата данни и използваме LiNQ 2 SQL за генериране на класовете или по-точно използваме Unplugged LINQ to SQL Generator за това. Той е стартиран като персонализиран инструмент, но разликата между генерираните класове е голяма болка във врата. Бихме искали автоматично да генерираме класовете, но да го изключим от контрола на версиите, така че се заех със задачата да създам задача msbuild. Намерих тази публикация и тази публикация, но не мога да реша това един сам. Добавих малко код, задачата изглежда така:

public class GenerateDesignerDC : Task
{
    public ITaskItem[] InputFiles { get; set; }
    public ITaskItem[] OutputFiles { get; set; }

    public override bool Execute()
    {
        var generatedFileNames = new List<string>();
        foreach (var task in InputFiles)
        {

            string inputFileName = task.ItemSpec;
            string outputFileName = Path.ChangeExtension(inputFileName, ".Designer.cs");
            string result;

            // Build code string
            var generator = new ULinqCodeGenerator("CSharp");
            string fileContent;
            using (FileStream fs = File.OpenRead(inputFileName))
            using (StreamReader rd = new StreamReader(fs))
            {
                fileContent = rd.ReadToEnd();
            }

            using (var destination = new FileStream(outputFileName, FileMode.Create))
            {
                byte[] bytes = Encoding.UTF8.GetBytes(generator.BuildCode(inputFileName, fileContent));
                destination.Write(bytes, 0, bytes.Length);
            }
            generatedFileNames.Add(outputFileName);
        }

        OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray();

        return true;
    }
}

Сега се опитвам да добавя персонализирана цел за това, наречена custom.target

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <CoreCompileDependsOn>$(CoreCompileDependsOn);GenerateToolOutput</CoreCompileDependsOn>
    </PropertyGroup>
    <UsingTask TaskName="BuildTasks.GenerateDesignerDC" AssemblyFile="BuildTasks.dll" />
    <Target Name="GenerateToolOutput" Inputs="@(dbml)" Outputs="@(dbml->'$(IntermediateOutputPath)%(FileName).designer.cs')">
        <GenerateDesignerDC InputFiles="@(dbml)" OutputFiles="@(dbml->'$(IntermediateOutputPath)%(FileName).designer.cs')">
            <Output ItemGroup="Compile" TaskParameter="OutputFiles" />
        </GenerateDesignerDC>
    </Target>
</Project>

Също така добавям необходимите ItemGroups към файла на проекта, както следва:

<ItemGroup>
    <AvailableItemName Include="dbml" />
</ItemGroup>
<ItemGroup>
    <Compile Include="@(dbml)" />
</ItemGroup>

И накрая добавям файловете към проекта със следното:

<dbml Include="DAL\SettingsDC.dbml">
    <SubType>Designer</SubType>
    <Generator>ULinqToSQLGenerator</Generator>
    <LastGenOutput>SettingsDC.designer.cs</LastGenOutput>
</dbml>

Това води до съобщение за грешка, което казва

Задачата "GenerateDesignerDC" има невалидна изходна спецификация. Атрибутът "TaskParameter" е задължителен и атрибутът "ItemName" или "PropertyName" трябва да бъде посочен (но не и двата).

Какво трябва да направя, за да работи това?


person mhenrixon    schedule 06.07.2010    source източник


Отговори (1)


Не сте декларирали изходно свойство във вашата задача. Трябва да използвате атрибута Output на свойството OutputFiles.

public class GenerateDesignerDC : Task
{
    [Required]
    public ITaskItem[] InputFiles { get; set; }

    [Output]
    public ITaskItem[] OutputFiles { get; set; }

    public override bool Execute()
    {
        var generatedFileNames = new List<string>();
        foreach (var task in InputFiles)
        {

            string inputFileName = task.ItemSpec;
            string outputFileName = Path.ChangeExtension(inputFileName, ".Designer.cs");
            string result;

            // Build code string
            var generator = new ULinqCodeGenerator("CSharp");
            string fileContent;
            using (FileStream fs = File.OpenRead(inputFileName))
            using (StreamReader rd = new StreamReader(fs))
            {
                fileContent = rd.ReadToEnd();
            }

            using (var destination = new FileStream(outputFileName, FileMode.Create))
            {
                byte[] bytes = Encoding.UTF8.GetBytes(generator.BuildCode(inputFileName, fileContent));
                destination.Write(bytes, 0, bytes.Length);
            }
            generatedFileNames.Add(outputFileName);
        }

        OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray();

        return true;
    }
}
person Julien Hoarau    schedule 07.07.2010
comment
Правилно, трябваше също да добавя ‹Output TaskParameter=OutputFiles Propertyname=OutputFiles /› - person mhenrixon; 07.07.2010