以编程方式调用EntityDeploy构建任务 [英] Invoke EntityDeploy build task programmatically

查看:69
本文介绍了以编程方式调用EntityDeploy构建任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Roslyn来编译,发出和运行C#源代码.但是,面对使用EntityFramework的项目时,我遇到了一个限制.

I'm using Roslyn to compile, emit and run C# source code. However, I've run into a limitation when faced with projects that use EntityFramework.

似乎仅仅发出编译文件是不够的,因为有一个EntityDeploy构建任务可以在发出DLL之后对其进行操作. (我相信它是在将DLL发出后将元数据工件嵌入到DLL中的.)

It seems that simply emitting the compilation isn't enough, as there is an EntityDeploy build task that manipulates the DLLs after they've been emitted. (I believe it is embedding Metadata Artifacts in the DLLs after they're emitted).

在我正在处理的.csproj文件中,我看到以下实体部署任务:

In the .csproj file I'm processing, I see the following entity deploy task:

<EntityDeploy Include="Models\Northwind.edmx">
  <Generator>EntityModelCodeGenerator</Generator>
  <LastGenOutput>Northwind.Designer.cs</LastGenOutput>
</EntityDeploy>

是否可以直接调用此构建任务并操纵我发出的DLL?

Is it possible to invoke this build task this directly and manipulate the DLLs I've emitted?

注意:我不想简单地调用msbuild.exe或对.csproj文件中的所有内容运行MSBuild.我正在构建的项目存在于内存中,但不在磁盘上,因此在我的情况下将无法正常工作.

Note: I don't want to simply call msbuild.exe or run MSBuild on everything in the .csproj file. The projects I'm building exist in memory, but not on disk, so that won't work in my case.

我正在尝试学习如何使用Microsoft.Build.Evaluation东西.我可以找到EntityDeploy任务,但是我对如何调用它(以及我应该提供的参数)一无所知.

I'm trying to learn how to use the Microsoft.Build.Evaluation stuff. I can find the EntityDeploy task, but I'm at a loss for how to invoke it (and for what parameters I should be providing).

var project = new Project(@"C:\Users\JoshVarty\Documents\Visual Studio 2015\Projects\WebApplication1\WebApplication1\WebApplication1.csproj");
//Get the entity deploy target? I'm not sure if this is a task or target.
var entityDeploy = project.Targets.Where(n => n.Key == "EntityDeploy").Single();

var projectTargetInstance = entityDeploy.Value;

我还尝试查看EntityDeploy构建任务,因为它存在于磁盘中.

I've also tried looking at the EntityDeploy build task as it exists on disk.

var entityDeployTask = new Microsoft.Data.Entity.Build.Tasks.EntityDeploy();
entityDeployTask.Sources = //I'm not sure where I can get the ITaskItem[] I need
entityDeployTask.EntityDataModelEmbeddedResources = //I'm not sure where I can get the ITaskItem[]
entityDeployTask.Execute();

我同时是MSBuildEntityFrameworkEntityDeploy的新手,所以如果我误用了术语或完全以错误的方式来使用我,请纠正我.

I'm simultaneously brand new to MSBuild, EntityFramework and EntityDeploy, so please correct me if I've misused terms or come at this the wrong way altogether.

推荐答案

我对EntityDeploy不熟悉,但是我会提供一些我收集到的信息,可能会对您有所帮助.

I'm not familiar with EntityDeploy, but I'll give some information that I've gathered that might help you.

如果您查看

If you look at the targets file you can see that there's an EntityDeploy target which relies on EntityDeploy, EntityDeploySplit, EntityDeploySetLogicalNames and EntityClean tasks.

当使用.edmx文件列表调用EntityDeploy目标时,会发生以下情况:

When the EntityDeploy target is called with list of .edmx files the following happens:

  1. EntityDeploySplit 是调用后,它会读取.edmx文件,并确定处理每个文件的结果是应该嵌入目标程序集中还是放置在目标程序集中.
  2. EntityDeploy 是从1调用NonEmbeddingItems,它将拆分.edmx文件并将结果放入OutputPath
  3. EntityDeploy 是从1调用EmbeddingItems,它将拆分.edmx文件并将结果放置在EntityDeployIntermediateResourcePath
  4. EntityDeploySetLogicalNames 是调用EntityDeployIntermediateResourcePath中的文件,以将每个文件上的元数据LogicalName设置为用于嵌入的逻辑名称(这是从EntityDeployIntermediateResourcePath开始的文件的相对路径,用斜杠替换为点)
  5. 调用
  6. EntityClean 来删除中间文件
  1. EntityDeploySplit is invoked, it reads the .edmx files and determines whether the results from processing each one should be embedded in the target assembly or placed alongside.
  2. EntityDeploy is called on NonEmbeddingItems from 1., it splits the .edmx files and places the result in OutputPath
  3. EntityDeploy is called on EmbeddingItems from 1., it splits the .edmx files and places the result in EntityDeployIntermediateResourcePath
  4. EntityDeploySetLogicalNames is called on the files in EntityDeployIntermediateResourcePath to set the metadata LogicalName on each file to the logical name to be used for embedding (It's just the relative path to the file from EntityDeployIntermediateResourcePath with slashes replaced by dots)
  5. EntityClean is called to remove the intermediate files

我还没有尝试过,但是应该可以依次使用

I haven't tried this, but it should be possible to call these in sequence to get the expected behavior using the Engine class:

 // Instantiate a new Engine object
 Engine engine = new Engine();

 // Point to the path that contains the .NET Framework 2.0 CLR and tools
 engine.BinPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.System)
+ @"\..\Microsoft.NET\Framework\v2.0.50727";
 var entityDeploySplitTask = new EntityDeploySplit();
 entityDeploySplitTask.Sources = new ITaskItem[] 
 {
   new TaskItem("Model.edmx")// path to .edmx file from .csproj
 };
 entityDeploySplitTask.BuildEngine = engine;
 entityDeploySplitTask.Execute();

 var entityDeployTask = new EntityDeploy();
 entityDeployTask.Sources = entityDeploySplitTask.NonEmbeddingItems
 entityDeployTask.OutputPath = "."; // path to the assembly output folder
 entityDeployTask.BuildEngine = engine;
 entityDeployTask.Execute();

 var entityDeployTask2 = new EntityDeploy();
 entityDeployTask2.Sources = entityDeploySplitTask.EmbeddingItems
 entityDeployTask2.OutputPath = "C:\Temp"; // path to an intermediate folder
 entityDeployTask2.BuildEngine = engine;
 entityDeployTask2.Execute();

 var entityDeploySetLogicalTask = new EntityDeploySetLogicalNames();
 entityDeploySetLogicalTask.Sources = Directory.EnumerateFiles("C:\Temp", "*.*", SearchOption.AllDirectories)
     .Select(f => new TaskItem(f)).ToArray();
 entityDeploySetLogicalTask.ResourceOutputPath = "C:\Temp"; // path to the intermediate folder
 entityDeploySetLogicalTask.BuildEngine = engine;
 entityDeploySetLogicalTask.Execute();

 foreach(var resourceFile in entityDeploySetLogicalTask.ResourcesToEmbed)
 {
    var fileName = resourceFile.GetMetadata("Identity");
    var logicalName = resourceFile.GetMetadata("LogicalName");
    //TODO: Embed filename using logicalName in the output assembly
    //You can embed them as normal resources by passing /resource to csc.exe
    //eg. /resource:obj\Debug\edmxResourcesToEmbed\Models\SampleEF.csdl,Models.SampleEF.csdl
 }

 //TODO: call EntityClean or just remove all files from the intermediate directory

这篇关于以编程方式调用EntityDeploy构建任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆