[英]Generate Server Side WCF Service automatically from existing API
如何在不使用WCF項目的情況下,通過WCF將每個方法的API暴露給由多個類組成的API。
例如,假設我有以下內容
public interface RainfallMonitor
{
[ExposeToWeb]
void RecordRainfall(string county, float rainfallInches);
[ExposeToWeb]
float GetTotalRainfall(string county);
void ClearRainfall(string county);
}
我知道我可以像往常一樣創建一個WCF服務庫,只需添加一個名為“RainfallMonitor”的WCF服務。
我正在探索的是......是否可能/合理地在編譯時為整個API生成所有WCF相關代碼而不實際生成類WCF服務。 可能使用ExposeToWeb
等屬性來表示通過服務公開哪些方法。 結果將像這樣:
RainfallAPI
項目中創建/修改類 RainfallService
項目/ dll。 實質上:
為了澄清:我不是在問自動生成客戶端存根,我問的是在服務器端創建服務。
我最近是這個圖書館的負責人: Fody 。 據我所知,它可以掛鈎構建過程並將IL注入到程序集中。 我不完全確定它是如何工作的,但是有可能通過IL搜索,找到具有ExposeToWeb
屬性的所有方法並使用它來將WCF服務的合同發送到程序集中。
但另一方面,如果您已經在類中添加了屬性,為什么不直接添加正確的WFC屬性,然后使用SvcUtil
在post build中生成合同?
編輯:這是一個如何使用svcutil
的示例:
C#:
[ServiceContract]
public interface IRainfallMonitor
{
[OperationContract]
void RecordRainfall(string county, float rainfallInches);
}
public class RainfallMonitor : IRainfallMonitor
{
public void RecordRainfall(string county, float rainfallInches)
{
// code
}
}
post build PowerShell:
$svcutil = "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\SvcUtil.exe"
$csc = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe"
$assembly = "bin/debug/ProjectWithoutWCF.dll"
$service = "ProjectWithoutWCF.RainfallMonitor"
$outputns = "ProjectWithoutWCF.RainfallMonitor.Service"
$outputdir = "bin/debug"
md svcutil_tmp
cd svcutil_tmp
& $svcutil /serviceName:"$service" "../$assembly"
& $svcutil *.wsdl *.xsd /importxmltypes /out:"output.cs" /n:"*,$outputns"
& $csc /target:library /out:$outputns.dll "output.cs"
cp "$outputns.dll" "../$outputdir"
cp output.config "../$outputdir/$outputns.dll.config"
cd ..
rm -r .\svcutil_tmp
在項目配置中你需要這樣的東西:
<system.serviceModel>
<services>
<service name="ProjectWithoutWCF.RainfallMonitor" >
<endpoint address="" binding="basicHttpBinding" contract="ProjectWithoutWCF.IRainfallMonitor">
</endpoint>
</service>
</services>
</system.serviceModel>
它有點繁瑣,你很可能需要對腳本和配置進行一些調整。 但結果是你有一個帶有WCF服務合同的ProjectWithoutWCF.RainfallMonitor.Service.dll
文件。
關於“我正在探索的是......是否可能/合理地在編譯時為整個API生成所有WCF相關代碼而不實際生成類WCF服務的可能/合理。”,有選項,但是他們都會做很多工作。
您需要編寫一個代碼生成應用程序/庫,它使用CSharpCodeProvider等類(也有一個用於VB)和反射來檢查您的庫作為后期構建步驟,在內存中構建您想要的代碼,並保存它作為DLL關閉。
此應用程序需要找到您創建的自定義屬性,指示它應該是WCF服務,並根據您定義的規則輸出WCF代碼。
實際上,您需要使用CodeDOM模型編寫代碼,這需要以非常不同的方式思考代碼。 不是每個人都能夠將他們的思想抽象到那個層次。
請記住,利用CodeDOM模型,您可以克服點頭提到的一些問題,例如要求可序列化的數據合同。 這可以添加,並由基於CodeDOM的反射庫輸出新的DLL。
通過周到的設計和相當多的工作,可以實現您正在尋求的輸出。 這只是一條黑暗的道路,有很多陷阱可以到達那里。
是的,這可以通過使用正確的工具進行適度的努力來完成。 如果您有Visual Studio,則您已經擁有Microsoft的T4代碼生成器。 它允許您通過編寫“文本模板”來生成代碼,這非常讓人聯想到ASP.NET的RAZOR語法。 使用T4,您實際上可以實例化現有類並使用反射來讀取所有類名和方法簽名,並最終生成WCF服務。 這並不難!
以下是Oleg Sych教程中的 T4模板示例:
<#@ template language=“C#v3.5” #>
<#@ output extension=“SQL” #>
<#@ assembly name=“Microsoft.SqlServer.ConnectionInfo” #>
<#@ assembly name=“Microsoft.SqlServer.Smo” #>
<#@ import namespace=“Microsoft.SqlServer.Management.Smo” #>
<#
Server server = new Server();
Database database = new Database(server, “Northwind”);
Table table = new Table(database, “Products”);
table.Refresh();
#>
create procedure <#= table.Name #>_Delete
<#
PushIndent(”\t”);
foreach (Column column in table.Columns)
{
if (column.InPrimaryKey)
WriteLine(”@” + column.Name + ” ” + column.DataType.Name);
}
PopIndent();
#>
as
delete from <#= table.Name #>
where
<#
PushIndent(”\t\t”);
foreach (Column column in table.Columns)
{
if (column.InPrimaryKey)
WriteLine(column.Name + ” = @” + column.Name);
}
PopIndent();
#>
輸出看起來像這樣:
create procedure Products_Delete
@ProductID int
as
delete from Products
where ProductID = @ProductID
當然,在您的示例中,您將使用現有類庫的反射而不是sql查詢。 您生成的WCf服務可以簡單地調用您現有的庫,這樣您就不必復制所有實際的域邏輯。
MSDN
您可以使用Roslyn,Roslyn是新的編譯器作為服務,您可以在其中解析C#文件並根據需要生成源代碼。
你可以在這里看到一些例子,
http://www.codeproject.com/Articles/302595/Roslyn-CTP-Three-Introductory-Projects
應該不那么困難。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.