MSBuild,运行自定义工具来生成 linq to sql 模型类的自定义任务?

发布于 2024-09-08 05:40:15 字数 3302 浏览 2 评论 0原文

我有以下场景。我们使用存储过程来访问数据库,并使用 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>

我还将必要的 ItemGroup 添加到项目文件中,如下所示:

<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”属性必须是 指定(但不是两者)。

我需要做什么才能使这项工作成功?

I have the following scenario. We use stored procedures to access the database and we use LiNQ 2 SQL to generate the classes or namely we use Unplugged LINQ to SQL Generator for this. It has been run as a custom tool but diffing the generated classes is a big pain in the neck. We would like to auto generate the classes but exclude it from version control so I set on the task of creating an msbuild task. Found this post and this post but I can't solve this one by myself. I added some code the task looks like the following:

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;
    }
}

Now I try to add a custom target for this called 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>

I also add the necessary ItemGroups to the project file like follows:

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

And finally I add the files to the project with the following:

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

This causes an error message saying

The "GenerateDesignerDC" task has an
invalid output specification. The
"TaskParameter" attribute is required,
and either the "ItemName" or
"PropertyName" attribute must be
specified (but not both).

What do I need to do to make this work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城泪 2024-09-15 05:40:15

您尚未在任务中声明输出属性。您必须在 OutputFiles 属性上使用 Output 属性。

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;
    }
}

You haven't declared an output property in your task. You have to use the Output attribute on OutputFiles property.

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文