以编程方式调用EntityDeploy构建任务 [英] Invoke EntityDeploy build task programatically
问题描述
似乎简单地发出编译是不够的,因为有一个code> EntityDeploy 构建任务,它们在发布后操作DLL。 (我相信它们在发布后将DLL中的元数据工件嵌入)。
在 .csproj
文件我正在处理,我看到以下实体部署任务:
< EntityDeploy Include =Models\Northwind.edmx >
< Generator> EntityModelCodeGenerator< / Generator>
< LastGenOutput> Northwind.Designer.cs< / LastGenOutput>
< / EntityDeploy>
是否可以直接调用此构建任务并操作我发出的DLL?
注意:我不想简单地调用 msbuild.exe
或运行 .csproj
文件中的所有内容都有 MSBuild
。我正在构建的项目存在于内存中,但不在磁盘上,因此在我的情况下不起作用。
我试过的内容:
我正在尝试学习如何使用 Microsoft.Build.Evaluation
的东西。我可以找到EntityDeploy任务,但是如何调用它(以及我应该提供哪些参数),我感到失落。
var project = new Project(@C:\Users\JoshVarty\Documents\Visual Studio 2015\Projects\WebApplication1\WebApplication1\WebApplication1.csproj);
//获取实体部署目标?我不知道这是一个任务还是目标。
var entityDeploy = project.Targets.Where(n => n.Key ==EntityDeploy)。Single();
var projectTargetInstance = entityDeploy.Value;
我也试过看看 EntityDeploy
构建任务,因为它存在于磁盘上。
var entityDeployTask = new Microsoft.Data.Entity.Build.Tasks.EntityDeploy() ;
entityDeployTask.Sources = //我不知道我可以在哪里得到ITaskItem []我需要
entityDeployTask.EntityDataModelEmbeddedResources = //我不知道我可以在哪里得到ITaskItem []
entityDeployTask.Execute();
我同时崭新的 MSBuild
, EntityFramework
和 EntityDeploy
,所以请纠正我,如果我滥用条款或完全错误的方式。
我不熟悉 EntityDeploy
,但我会给我一些可能会帮助你的信息。
如果你看看目标文件,您可以看到有一个 EntityDeploy
目标依赖于 EntityDeploy
, EntityDeploySplit
, EntityDeploySetLogicalNames
和 EntityClean
任务。
EntityDeploy
目标被调用,列表为 .edmx
文件发生以下情况:
- EntityDeploySplit 被调用,它读取
.edmx
文件,并确定处理每个文件的结果是否应嵌入到目标程序集中或放在旁边。 - EntityDeploy 在1. $
NonEmbeddingItems
之间调用,它将.edmx
文件,并将结果放在OutputPath
- EntityDeploy 在
EmbeddingItems
从1.,它分割.edmx
文件,并将结果放在EntityDeployIntermediateResourcePath
- EntityDeploySetLogicalNames 在
EntityDeployIntermediateResourcePath $ c中的文件上调用$ c>将每个文件上的元数据
LogicalName
设置为要用于嵌入的逻辑名称(这只是文件的相对路径,来自EntityDeployIntermediateResourcePath
以斜线替换为点) - EntityClean 被删除中间文件
我没有尝试这样做,但应该可以按顺序调用这些,以使用引擎类:
//实例化一个新的引擎对象
引擎engine = new Engine();
//指向包含.NET Framework 2.0 CLR和工具的路径
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)// .csproj
}中的.edmx文件的路径;
entityDeploySplitTask.BuildEngine = engine;
entityDeploySplitTask.Execute();
var entityDeployTask = new EntityDeploy();
entityDeployTask.Sources = entityDeploySplitTask.NonEmbeddingItems
entityDeployTask.OutputPath =。; //程序集输出文件夹的路径
entityDeployTask.BuildEngine = engine;
entityDeployTask.Execute();
var entityDeployTask2 = new EntityDeploy();
entityDeployTask2.Sources = entityDeploySplitTask.EmbeddingItems
entityDeployTask2.OutputPath =C:\Temp; //中间文件夹的路径
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; //中间文件夹的路径
entityDeploySetLogicalTask.BuildEngine = engine;
entityDeploySetLogicalTask.Execute();
foreach(entityDeploySetLogicalTask.ResourcesToEmbed中的var resourceFile)
{
var fileName = resourceFile.GetMetadata(Identity);
var logicalName = resourceFile.GetMetadata(LogicalName);
// TODO:在输出程序集中嵌入使用logicalName的文件名
//您可以将它们作为普通资源嵌入到csc.exe
// eg中。 /resource:obj\Debug\edmxResourcesToEmbed\Models\SampleEF.csdl,Models.SampleEF.csdl
}
// TODO:调用EntityClean,或者只是删除所有文件中间目录
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.
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).
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>
Is it possible to invoke this build task this directly and manipulate the DLLs I've emitted?
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.
What I've tried:
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;
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();
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.
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.
When the EntityDeploy
target is called with list of .edmx
files the following happens:
- 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. - EntityDeploy is called on
NonEmbeddingItems
from 1., it splits the.edmx
files and places the result inOutputPath
- EntityDeploy is called on
EmbeddingItems
from 1., it splits the.edmx
files and places the result inEntityDeployIntermediateResourcePath
- EntityDeploySetLogicalNames is called on the files in
EntityDeployIntermediateResourcePath
to set the metadataLogicalName
on each file to the logical name to be used for embedding (It's just the relative path to the file fromEntityDeployIntermediateResourcePath
with slashes replaced by dots) - 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屋!