如何在 F# 中声明一个可以通过 WebJob 的 JobHost.CallAsync 调用的函数?
How can I declare a function in F# that can be invoked via WebJob's JobHost.CallAsync?
在 C# WebJob 中,我可以像这样手动调用 public 静态 class 方法:
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
namespace foo
{
public class Program
{
[NoAutomaticTrigger]
public static void Go(TraceWriter log) { ... }
static void Main()
{
var host = new JobHost();
var methodInfo = typeof(Program).GetMethod("Go");
host.Call(methodInfo);
host.RunAndBlock();
}
methodInfo 是一个 System.Reflection.MethodInfo,在调试器中我可以看到它有属性 Public | Static | HideBySig
和 CustomAttributes Microsoft.Azure.WebJobs.NoAutomaticTriggerAttribute
.
我正在尝试在 F# 中执行此操作。这是我目前所拥有的:
type Foo() =
[<NoAutomaticTrigger>]
static member Go (log:TraceWriter) =
log.Info "hello!"
[<EntryPoint>]
let main argv =
let theType = typedefof<Foo>
let methodInfo = theType.GetMethods() |> Seq.find(fun t -> t.Name = "Go")
host.Call(methodInfo)
host.RunAndBlock()
WebJobs 运行时不喜欢它:
System.InvalidOperationException
HResult=0x80131509
Message='Void Go(Microsoft.Azure.WebJobs.Host.TraceWriter)' can't be invoked from Azure WebJobs SDK. Is it missing Azure WebJobs SDK attributes?
Source=Microsoft.Azure.WebJobs.Host
StackTrace:
at Microsoft.Azure.WebJobs.JobHost.Validate(IFunctionDefinition function, Object key)
at Microsoft.Azure.WebJobs.JobHost.<CallAsyncCore>d__37.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.WebJobs.JobHost.Call(MethodInfo method)
at Program.main(String[] argv) in C:\path\to\project\Program.fs:line 110
我的 F# methodInfo 有 NoAutomaticTrigger
属性。它还具有 Public 和 Static,但缺少 HideBySig。这可能很重要吗?我应该比较 MethodInfos 的其他部分吗?
这是来自 webjobs sdk 的相关来源:https://github.com/Azure/azure-webjobs-sdk/blob/v2.2.0/src/Microsoft.Azure.WebJobs.Host/JobHost.cs#L306
不管怎样,我已经能够成功地使用 F# 中的 TimerTrigger 和 ServiceBusTrigger;我正在努力解决的就是这种手动调用模式。
接下来我打算筛选 webjobs 源并尝试弄清楚它到底在寻找什么,但我希望有一些明显的 F# and/or webjobs 经验丰富的人可以告诉我。
通过 WebJobs 源进行调试,我最终在
DefaultTypeLocator, which picks up classes that are marked IsPublic. I experimented with my F# declarations, but couldn't seem to achieve that; I only managed to produce IsNestedPublic.
所以我尝试了另一种方法:我没有尝试编写可由现有 WebJobs 运行时发现的 F# 函数,而是覆盖了发现逻辑:
type myTypeLocator() =
interface ITypeLocator with
member this.GetTypes () =
new System.Collections.Generic.List<Type>([ typedefof<Foo> ]) :> IReadOnlyList<Type>
...
let config = new JobHostConfiguration (
DashboardConnectionString = dashboardConnectionString,
StorageConnectionString = storageConnectionString,
TypeLocator = new myTypeLocator()
)
let host = new JobHost(config)
这成功了:我的功能被发现了,我能够 JobHost.Call 它们。
在 C# WebJob 中,我可以像这样手动调用 public 静态 class 方法:
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
namespace foo
{
public class Program
{
[NoAutomaticTrigger]
public static void Go(TraceWriter log) { ... }
static void Main()
{
var host = new JobHost();
var methodInfo = typeof(Program).GetMethod("Go");
host.Call(methodInfo);
host.RunAndBlock();
}
methodInfo 是一个 System.Reflection.MethodInfo,在调试器中我可以看到它有属性 Public | Static | HideBySig
和 CustomAttributes Microsoft.Azure.WebJobs.NoAutomaticTriggerAttribute
.
我正在尝试在 F# 中执行此操作。这是我目前所拥有的:
type Foo() =
[<NoAutomaticTrigger>]
static member Go (log:TraceWriter) =
log.Info "hello!"
[<EntryPoint>]
let main argv =
let theType = typedefof<Foo>
let methodInfo = theType.GetMethods() |> Seq.find(fun t -> t.Name = "Go")
host.Call(methodInfo)
host.RunAndBlock()
WebJobs 运行时不喜欢它:
System.InvalidOperationException
HResult=0x80131509
Message='Void Go(Microsoft.Azure.WebJobs.Host.TraceWriter)' can't be invoked from Azure WebJobs SDK. Is it missing Azure WebJobs SDK attributes?
Source=Microsoft.Azure.WebJobs.Host
StackTrace:
at Microsoft.Azure.WebJobs.JobHost.Validate(IFunctionDefinition function, Object key)
at Microsoft.Azure.WebJobs.JobHost.<CallAsyncCore>d__37.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.WebJobs.JobHost.Call(MethodInfo method)
at Program.main(String[] argv) in C:\path\to\project\Program.fs:line 110
我的 F# methodInfo 有 NoAutomaticTrigger
属性。它还具有 Public 和 Static,但缺少 HideBySig。这可能很重要吗?我应该比较 MethodInfos 的其他部分吗?
这是来自 webjobs sdk 的相关来源:https://github.com/Azure/azure-webjobs-sdk/blob/v2.2.0/src/Microsoft.Azure.WebJobs.Host/JobHost.cs#L306
不管怎样,我已经能够成功地使用 F# 中的 TimerTrigger 和 ServiceBusTrigger;我正在努力解决的就是这种手动调用模式。
接下来我打算筛选 webjobs 源并尝试弄清楚它到底在寻找什么,但我希望有一些明显的 F# and/or webjobs 经验丰富的人可以告诉我。
通过 WebJobs 源进行调试,我最终在 DefaultTypeLocator, which picks up classes that are marked IsPublic. I experimented with my F# declarations, but couldn't seem to achieve that; I only managed to produce IsNestedPublic.
所以我尝试了另一种方法:我没有尝试编写可由现有 WebJobs 运行时发现的 F# 函数,而是覆盖了发现逻辑:
type myTypeLocator() =
interface ITypeLocator with
member this.GetTypes () =
new System.Collections.Generic.List<Type>([ typedefof<Foo> ]) :> IReadOnlyList<Type>
...
let config = new JobHostConfiguration (
DashboardConnectionString = dashboardConnectionString,
StorageConnectionString = storageConnectionString,
TypeLocator = new myTypeLocator()
)
let host = new JobHost(config)
这成功了:我的功能被发现了,我能够 JobHost.Call 它们。