Используя F# и Caliburn.Micro вместе

Как я понимаю, Caliburn.Micro выполняет значительную часть работ по автоматическому подключению и монтажу для проекта WPF на основе соглашений; используя MVVM.

Вопрос: Есть ли какие-либо специфичные для C# детали в Caliburn.Micro; которые использовали некоторые C# -только функции? Какие части Caliburn.Micro нельзя использовать с кодом F#? Что я теряю при использовании F#?

2 ответа

Решение

К сожалению, Caliburn.Micro и F# не очень хорошо работают вместе.

Например, Caliburn.Micro обрабатывает представления как обычные классы во время сопоставления соглашений (посредством отражения), что справедливо для C# - представления являются частичными классами.

F# не поддерживает частичные классы, а представления - только файлы XAML. Это означает, что они не могут быть решены Caliburn.Micro. Это также означает, что у вас будут проблемы с подключением контейнера IoC в загрузчике, потому что он не сможет создавать представления - по крайней мере, без ручной регистрации в Application.LoadComponent и тому подобное.

Настройка бустреппера также была проблемой, потому что вы должны указать ключ в App.xaml, но по какой-то причине этот ключ не соответствовал классу. Bootstrapper<T> также проходит bool useApplication = true в BootstrapperBase по умолчанию - и у F# были разные проблемы в зависимости от того, был установлен этот флаг или нет, к сожалению, я не помню деталей. Это потому, что в F# вы сами подключаете точку входа к приложению, а Caliburn.Micro создан для автоматического перехвата этого шага. Это вызывает конфликты...

Если вы заставите его работать, полностью переопределив механизм разрешения соглашений и согнув любой контейнер IoC по своему желанию, вы получите больше возможностей. На мой взгляд, в настоящее время слишком много трения.

Лично я бы установил базовую основу для приложения на C# с использованием Caliburn.Micro и выполнил "реальную работу" на F#. В качестве альтернативы, я думаю, что вы можете даже иметь модели представлений, написанные на F# в отдельном проекте, представления в C# проекте, тогда вам просто нужно будет отрегулировать, как поиск соглашения работает в загрузчике. Я не совсем уверен в этом подходе, поэтому ваш пробег может меняться и действовать с осторожностью.

Это хороший вопрос. Если вы справитесь с этим, обязательно сообщите нам, как это происходит. Я искал Caliburn для стороннего проекта, но я не добился большого прогресса в этом.

Итак, чтобы начать, то, что вы, возможно, уже наткнулись на:

Перегрузка лямбда-выражения в NotifyOfPropertyChange

Основной метод для вызова событий PropertyChanged имеет два переопределения. Один, который принимает имя свойства в виде строки, а другой - лямбда-выражение. Последний использует хитрый трюк / уродливый хак для извлечения имени свойства из тела выражения. Это дает вам хороший, лаконичный синтаксис в C#, который до некоторой степени проверяется компилятором:

public string SomeProp
{
    get { return someField; }
    set
    {
        someField = value;
        NotifyOfPropertyChange(() => SomeProp);
    }
}

Но это не очень хорошо подходит для F#. Вы можете сделать выбор либо к строковому, либо добавить его в кавычки. Я использовал что-то вроде этого:

let notify<'a> (notifier: PropertyChangedBase) (expr: Expr<'a>) =
    let name =
        match expr with
        | PropertyGet (_, pi, _) -> pi.Name
        | _ -> failwith "Can't get property name to notify"
    notifier.NotifyOfPropertyChange(name)

Который назывался так:

member this.SomeProp 
    with get () = 
        someField
    and set(value) = 
        someField <- value
        notify this <@ this.SomeProp @>

Я полагаю, что вы можете сделать еще один шаг вперед и превратить его в свой собственный класс PropertyChanged, построенный поверх PropertyChangedBase.

Другие вопросы по тегам