F# 中的内联 C# 对象创建
Inline C# Object Creation in F#
我正在尝试在某些 F# 代码中与 C# 库互操作。将以下 C# 视为我正在使用的库(或跳过下面以首先查看我正在使用的实际库):
public class Options
{
public Options(string name)
{
Name = name;
}
public string Name { get; }
public string SomeProperty { get; set; }
}
public class ServiceBuilder
{
public ServiceBuilder ApplyOptions(Options options)
{
//Apply Options in some way
return this;
}
public TheService Build()
{
return new TheService();
}
}
public class TheService
{
}
然后我尝试创建服务但要保持流畅我有以下 F# 代码:
//Valid Approach but not inlined :(
let options = Options("Test")
options.SomeProperty <- "SomeValue"
let theService =
ServiceBuilder()
.ApplyOptions(options)
.Build();
//Invalid Approach because SomeProperty is not virtual
let theService2 =
ServiceBuilder()
.ApplyOptions({
new Options("Test2") with
member _.SomeProperty = "SomeValue2"
})
.Build()
有没有什么方法可以让我在尝试创建“theService2”的 F# 中以 inline 的方式进行初始化?在 C# 中,我只使用对象初始化器。 F# 对象表达式已出局,因为我无法控制 class 来使 属性 虚拟。
对于我上面的 C# 模拟的额外上下文,我专门尝试使用 Serilog.Sinks.ElasticSearch nuget 包创建一个 Serilog Logger,并在 F# 中大致执行下面的代码(同样,inlined 如果可能的话):
var loggerConfig = new LoggerConfiguration()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200") ){
AutoRegisterTemplate = true,
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6
});
在 F# 中,您还可以 assign values to properties at initialization,因此要在单个表达式中创建 Options
实例,您可以执行以下操作:
Options("Test", SomeProperty="SomeValue")
对于从 C# 直接翻译 - 属性 初始化程序是可行的方法,正如@rob.earwaker 的回答中所建议的那样。
但是,还要注意在 F# 中 一切都是表达式。没有像 C# 中那样的“语句”,每段代码都有某种结果。这也适用于“复合”,也就是说,代码片段,例如 let
块。这意味着,即使您不想使用 属性 初始化程序,您仍然可以进行内联初始化:
let service =
ServiceBuilder()
.ApplyOptions(
let o = Options("Test")
o.SomeProperty <- "SomeValue"
o
)
.Build()
或使用 let .. in
和分号将所有内容放在同一行:
let service =
ServiceBuilder()
.WithOptions(let o = Options("Test") in o.SomeProperty <- "SomeValue"; o)
.Build()
与 C# 不同,此方法也适用于将初始化分解为可重用的部分:
let service =
ServiceBuilder()
.WithOptions(let o = Options("bar") in mutateSomeOptions(o); mutateOtherOptions(o); o)
.Build()
我正在尝试在某些 F# 代码中与 C# 库互操作。将以下 C# 视为我正在使用的库(或跳过下面以首先查看我正在使用的实际库):
public class Options
{
public Options(string name)
{
Name = name;
}
public string Name { get; }
public string SomeProperty { get; set; }
}
public class ServiceBuilder
{
public ServiceBuilder ApplyOptions(Options options)
{
//Apply Options in some way
return this;
}
public TheService Build()
{
return new TheService();
}
}
public class TheService
{
}
然后我尝试创建服务但要保持流畅我有以下 F# 代码:
//Valid Approach but not inlined :(
let options = Options("Test")
options.SomeProperty <- "SomeValue"
let theService =
ServiceBuilder()
.ApplyOptions(options)
.Build();
//Invalid Approach because SomeProperty is not virtual
let theService2 =
ServiceBuilder()
.ApplyOptions({
new Options("Test2") with
member _.SomeProperty = "SomeValue2"
})
.Build()
有没有什么方法可以让我在尝试创建“theService2”的 F# 中以 inline 的方式进行初始化?在 C# 中,我只使用对象初始化器。 F# 对象表达式已出局,因为我无法控制 class 来使 属性 虚拟。
对于我上面的 C# 模拟的额外上下文,我专门尝试使用 Serilog.Sinks.ElasticSearch nuget 包创建一个 Serilog Logger,并在 F# 中大致执行下面的代码(同样,inlined 如果可能的话):
var loggerConfig = new LoggerConfiguration()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200") ){
AutoRegisterTemplate = true,
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6
});
在 F# 中,您还可以 assign values to properties at initialization,因此要在单个表达式中创建 Options
实例,您可以执行以下操作:
Options("Test", SomeProperty="SomeValue")
对于从 C# 直接翻译 - 属性 初始化程序是可行的方法,正如@rob.earwaker 的回答中所建议的那样。
但是,还要注意在 F# 中 一切都是表达式。没有像 C# 中那样的“语句”,每段代码都有某种结果。这也适用于“复合”,也就是说,代码片段,例如 let
块。这意味着,即使您不想使用 属性 初始化程序,您仍然可以进行内联初始化:
let service =
ServiceBuilder()
.ApplyOptions(
let o = Options("Test")
o.SomeProperty <- "SomeValue"
o
)
.Build()
或使用 let .. in
和分号将所有内容放在同一行:
let service =
ServiceBuilder()
.WithOptions(let o = Options("Test") in o.SomeProperty <- "SomeValue"; o)
.Build()
与 C# 不同,此方法也适用于将初始化分解为可重用的部分:
let service =
ServiceBuilder()
.WithOptions(let o = Options("bar") in mutateSomeOptions(o); mutateOtherOptions(o); o)
.Build()