代码之家  ›  专栏  ›  技术社区  ›  mhenrixon

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

  •  3
  • mhenrixon  · 技术社区  · 15 年前

    我有以下场景。我们使用存储过程访问数据库,并使用Linq2SQL来生成类,也就是说,我们使用unplugged LINQ to SQL Generator 为此。它已经作为一个自定义工具运行,但是区分生成的类是一个很大的难题。我们希望自动生成类,但将其从版本控制中排除,因此我设置了创建msbuild任务的任务。发现 this post this post 但我自己解决不了这个问题。我添加了一些代码,任务如下:

    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>
        <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”属性是必需的, 以及“项目名称”或 “propertyname”属性必须为 已指定(但不能同时指定)。

    我需要做什么才能使这项工作有效?

    1 回复  |  直到 15 年前
        1
  •  10
  •   Julien Hoarau    15 年前

    您尚未在任务中声明输出属性。你必须使用 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;
        }
    }