我正在研究IronJS,我们的一个源文件变得非常长。
现在,我正在努力让.NET互操作。我将TryBinaryOperation
方法添加到Undefined
,以便C#可以使用未定义值的JavaScript语义。
但是,这会引入对Operators
类型的依赖,这会导致循环依赖。
Runtime.fs:
type BoxedValue() =
struct
// Contains IsUndefined and get_Undefined, referencing the Undefined class, below.
...
and type Undefined() =
inherit DynamicObject()
...
override x.TryBinaryOperation(binder:BinaryOperationBinder, arg:obj, result:obj byref) : bool =
// Here, we are referencing BoxedValue, above.
result <- Operators.add(Und, BoxedValue.Box(arg))
true
...
Operators.fs:
type Operators =
...
// Here, we are referencing BoxedValue.
static member add(BoxedValue l, BoxedValue r)
...
所以,我们有这组依赖关系:
理想情况下,我们希望将每个文件拆分为自己的文件。
F#中是否可能存在跨文件循环依赖关系?
答案 0 :(得分:6)
没有直接的方法来编写在单独文件中定义的类型之间的循环依赖关系(在当前版本的F#中)。通常,解决问题的方法是破坏其中一个依赖项并允许某种形式的参数化。然后,您可以填充孔以便稍后构建循环引用。
在您的示例中,您可以合理地轻松地参数化Undefined
类型,以引用Operators
作为参数。如果您需要更多功能,则可以使用界面。对于单个函数(如Operators.add
),您可以编写如下内容:
and type Undefined() =
inherit DynamicObject()
...
// To be specified by code defined later
// (this can either be a function or an interface implementation)
static let mutable addition = (fun x y -> failwith "not initialized")
static member SetAddition(f) = addition <- f
override x.TryBinaryOperation
(binder:BinaryOperationBinder, arg:obj, result:obj byref) : bool =
// Here, we are referencing BoxedValue, above.
result <- addition(Und, BoxedValue.Box(arg))
true
Operators.fs
中的代码将提供实现:
type Operators =
...
// Static constructor of the `Operators` type
static do Undefined.SetAddition(Operators.add)
....
// Here, we are referencing BoxedValue.
static member add(BoxedValue l, BoxedValue r)
唯一棘手的事情是你需要确保Operators
的静态构造函数在第一次使用Undefined
类型之前被调用。这取决于您的具体情况,但通常有一些方法可以做到这一点。 (可能有一些主要类型可以运行初始化)