简体   繁体   English

从现有API自动生成服务器端WCF服务

[英]Generate Server Side WCF Service automatically from existing API

How would a person go about exposing method per method an API comprised of several classes through WCF without using a WCF project. 如何在不使用WCF项目的情况下,通过WCF将每个方法的API暴露给由多个类组成的API。

For example, let's say I have the following 例如,假设我有以下内容

public interface RainfallMonitor
{
    [ExposeToWeb]
    void RecordRainfall(string county, float rainfallInches);

    [ExposeToWeb]
    float GetTotalRainfall(string county);

    void ClearRainfall(string county);
}

I understand I could create a WCF service library as usual and just add a WCF service called "RainfallMonitor". 我知道我可以像往常一样创建一个WCF服务库,只需添加一个名为“RainfallMonitor”的WCF服务。

What I'm exploring is... is it possible/reasonable to somehow generate all of the WCF related code at compile time for an entire API without actually making the classes WCF services. 我正在探索的是......是否可能/合理地在编译时为整个API生成所有WCF相关代码而不实际生成类WCF服务。 Possibly using attributes such as ExposeToWeb to denote which methods to expose via the services. 可能使用ExposeToWeb等属性来表示通过服务公开哪些方法。 The resultant would function like this: 结果将像这样:

  1. Create/modify classes in project called RainfallAPI 在名为RainfallAPI项目中创建/修改类
  2. Compile and have another project/dll generated called RainfallService automatically. 编译并自动生成另一个名为RainfallService项目/ dll。

Essentially: 实质上:

  • If this is possible what approach could I take to actually implement it? 如果可行,我可以采取什么方法来实际实施呢?
  • What serious pitfalls could I run into? 我可能遇到什么严重的陷阱?
  • Is there any existing codebase that does something similar I could look into for inspiration 是否有任何现有的代码库可以做类似的事情我可以寻找灵感

For clarification: I am not asking about auto-generating the client stub, I am asking about creating services on the server side. 为了澄清:我不是在问自动生成客户端存根,我问的是在服务器端创建服务。

I recently head of this library: Fody . 我最近是这个图书馆的负责人: Fody As I understand, it makes it possible to hook into the build process and inject IL into the assembly. 据我所知,它可以挂钩构建过程并将IL注入到程序集中。 I'm not completely sure how it works, but it might be possible to search though the IL, find all the methods with the ExposeToWeb attribute and use that to emit the contract for the WCF service in to the assembly. 我不完全确定它是如何工作的,但是有可能通过IL搜索,找到具有ExposeToWeb属性的所有方法并使用它来将WCF服务的合同发送到程序集中。

But on the other hand, if you are already adding attributes to the class, why not just add the correct WFC attributes to begin with, and then use SvcUtil to generate the contracts in post build? 但另一方面,如果您已经在类中添加了属性,为什么不直接添加正确的WFC属性,然后使用SvcUtil在post build中生成合同?

EDIT: Here is an example of how you could use svcutil : 编辑:这是一个如何使用svcutil的示例:

C#: 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: 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

and you will need something like this in you project config: 在项目配置中你需要这样的东西:

<system.serviceModel>
  <services>
    <service name="ProjectWithoutWCF.RainfallMonitor" >
      <endpoint address="" binding="basicHttpBinding" contract="ProjectWithoutWCF.IRainfallMonitor">
      </endpoint>
    </service>
  </services>
</system.serviceModel>

Its a little fiddly and you will most likely need some tweaking to the script and the config. 它有点繁琐,你很可能需要对脚本和配置进行一些调整。 But the result is that you have a ProjectWithoutWCF.RainfallMonitor.Service.dll file with the WCF service contracts. 但结果是你有一个带有WCF服务合同的ProjectWithoutWCF.RainfallMonitor.Service.dll文件。

For your question regarding "What I'm exploring is... is it possible/reasonable to somehow generate all of the WCF related code at compile time for an entire API without actually making the classes WCF services.", there are options, but they will all take a lot of work. 关于“我正在探索的是......是否可能/合理地在编译时为整个API生成所有WCF相关代码而不实际生成类WCF服务的可能/合理。”,有选项,但是他们都会做很多工作。

You would need to write a code generation application/library that utilizes classes such as CSharpCodeProvider (there is one for VB as well) and reflection to inspect your library as a post build step, build the code that you want in memory, and save it off as a DLL. 您需要编写一个代码生成应用程序/库,它使用CSharpCodeProvider等类(也有一个用于VB)和反射来检查您的库作为后期构建步骤,在内存中构建您想要的代码,并保存它作为DLL关闭。

This application would need to find a custom attribute you create that indicates that it should be a WCF service, and output WCF code based upon the rules you define. 此应用程序需要找到您创建的自定义属性,指示它应该是WCF服务,并根据您定义的规则输出WCF代码。

In effect you need to write code using the CodeDOM model, which requires thinking about code in a much different fashion. 实际上,您需要使用CodeDOM模型编写代码,这需要以非常不同的方式思考代码。 Not everyone is able to abstract their thinking to that level. 不是每个人都能够将他们的思想抽象到那个层次。

Keep in mind that utilizing the CodeDOM model, you can overcome some of the issues that nodots mentioned such as requiring serializable for data contracts. 请记住,利用CodeDOM模型,您可以克服点头提到的一些问题,例如要求可序列化的数据合同。 This could be added and a new DLL be output by your CodeDOM based reflection library. 这可以添加,并由基于CodeDOM的反射库输出新的DLL。

Through thoughtful design and quite a bit of work, it is possible to achieve the output you are seeking. 通过周到的设计和相当多的工作,可以实现您正在寻求的输出。 It is just a dark road with lots of pitfalls to get there. 这只是一条黑暗的道路,有很多陷阱可以到达那里。

Yes, this can be done, with moderate effort using the right tools. 是的,这可以通过使用正确的工具进行适度的努力来完成。 If you have Visual Studio, you already have Microsoft's T4 code generator. 如果您有Visual Studio,则您已经拥有Microsoft的T4代码生成器。 It allows you to generate code by writing "text templates", which are very reminiscent of ASP.NET's RAZOR syntax. 它允许您通过编写“文本模板”来生成代码,这非常让人联想到ASP.NET的RAZOR语法。 Using T4, you can actually instantiate your existing classes and use reflection to read all the class names and method signatures, and ultimately generate your WCF services. 使用T4,您实际上可以实例化现有类并使用反射来读取所有类名和方法签名,并最终生成WCF服务。 It's not that hard! 这并不难!

Here's a sample T4 template from Oleg Sych's tutorial : 以下是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();
#>

The output would look like this: 输出看起来像这样:

create procedure Products_Delete
    @ProductID int
as
    delete from Products
    where ProductID = @ProductID

Of course, your example, you'd use reflection on your existing class library instead of sql queries. 当然,在您的示例中,您将使用现有类库的反射而不是sql查询。 The WCf services that you generate can simply call your existing library, so that you don't have to copy all the actual domain logic. 您生成的WCf服务可以简单地调用您现有的库,这样您就不必复制所有实际的域逻辑。

MSDN MSDN

https://msdn.microsoft.com/en-us/library/bb126445.aspx https://msdn.microsoft.com/en-us/library/bb126445.aspx

You can use Roslyn, Roslyn is new compiler as service, where in you can parse C# file and generate source code as you need. 您可以使用Roslyn,Roslyn是新的编译器作为服务,您可以在其中解析C#文件并根据需要生成源代码。

You can see some examples here, 你可以在这里看到一些例子,

http://www.codeproject.com/Articles/302595/Roslyn-CTP-Three-Introductory-Projects http://www.codeproject.com/Articles/302595/Roslyn-CTP-Three-Introductory-Projects

It should not be that difficult. 应该不那么困难。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM