Изменяемый F # без начального значения для MEF - PullRequest
1 голос
/ 12 ноября 2011

У меня есть несколько модулей, которые экспортируют интерфейс IModule.Так что в основной программе у меня нет проблем

...
let mutable modules = Seq.empty
[<ImportMany>]
member x.Modules
    with get():IEnumerable<Lazy<IModule, IModuleData>> = modules
    and set(a) = modules <- a
...

Но теперь мне нужно открыть интерфейс для этих модулей.Таким образом, каждый модуль будет импортировать отдельный интерфейс

...
let mutable parent:IParent = ?
[<Import>]
member x.Parent
    with get():IParent = parent
    and set(a) = parent <- a
...

Итак, моя проблема в том, как мне создать своего изменяемого "родителя", когда у меня нет исходного значения для него?Кроме того, это подходящий способ представить API обратно компонентам?

Ответы [ 3 ]

6 голосов
/ 12 ноября 2011

Использование Unchecked.defaultof<_> должно помочь, но это означает, что вы обходите систему типа F #, что может быть опасным занятием - система пытается предотвратить случайную разыменование значений null (и получение NullReferenceException).

Типы, объявленные в F #, не имеют null в качестве правильного значения, что является попыткой устранить обычные ошибки, вызванные null. Чистый подход F # заключается в использовании типов опций для представления факта отсутствия значения:

let mutable parent:option<IParent> = None

[<Import>] 
member x.Parent 
   with get():IParent = 
      match parent with
      | Some p -> p
      | None -> failwith "TODO: Throw some reasonable exception here!"
   and set(a) = parent <- Some(a)

Если вы просто хотите сказать, что IParent может иметь значение null (возможно, потому, что вам нужно использовать его в некотором коде C #, который в любом случае будет игнорировать ограничение F #), тогда вы можете пометить определение типа, используя специальный атрибут, который позволяет использовать null с типом.

[<AllowNullLiteral>]
type IParent = 
  abstract DoStuff : unit -> unit

Тогда вы можете написать let mutable parent:IParent = null. Преимущество этого подхода заключается в том, что вы также можете легко проверить, является ли значение null (используя просто if parent <> null then ...), что не так очевидно при использовании Unchecked.defaultof<_>.

1 голос
/ 12 ноября 2011
let mutable parent = Unchecked.defaultof<IParent>

должен добиться цели.

0 голосов
/ 12 ноября 2011

Следуя тому, что объяснил Томас, вы, вероятно, должны поместить свои импорта непосредственно в ваш конструктор.Это позволит вашему коду быть немного более идиоматичным.

...