2016-02-02 3 views
3

В моем first attempt создать провайдер типа, у меня есть ProvidedTypeDefinition для сообщения:F # Как создать экземпляр предоставленного типа

// Message type 
      let mTy = ProvidedTypeDefinition(asm, ns, message.Key, Some(typeof<ValueType>), 
         HideObjectMethods = true, IsErased = false) 
      // Direct buffer 
      let bufferField = ProvidedField("_directBuffer", typeof<IDirectBuffer>) 
      mTy.AddMember bufferField 

      let mCtor1 = 
      ProvidedConstructor(
       [ProvidedParameter("buffer", typeof<IDirectBuffer>)], 
       InvokeCode = fun args -> 
       match args with 
       | [this;buffer] -> 
        Expr.FieldSet (this, bufferField, <@@ %%buffer:IDirectBuffer @@>) 
       | _ -> failwith "wrong ctor params" 
      ) 
      mTy.AddMember mCtor1 

Затем нужно создать экземпляр этого типа в методе другого предоставленного типа. Я делаю это:

let mMethod = ProvidedMethod(message.Key, [ProvidedParameter("buffer", typeof<IDirectBuffer>)], mTy) 
      mMethod.InvokeCode <- (fun [this;buffer] -> 
       let c = mTy.GetConstructors().Last() 
       Expr.NewObject(c, [ buffer ]) 
     ) 

ILSpy показывает следующий C# код эквивалент метода:

public Car Car(IDirectBuffer buffer) 
     { 
      return new Car(buffer); 
     } 

, и это также показывает, что Car структура присутствует в тестовой сборке (этот тест сборки строит ОК если я не доступ к Car метод):

enter image description here

Но когда я пытаюсь создать Автомобиль с помощью метода, как это:

type CarSchema = SbeProvider<"Path\to\SBETypeProvider\SBETypeProvider\Car.xml"> 
module Test = 
    let carSchema = CarSchema() 
    let car = carSchema.Car(null) 

я получаю следующие ошибки:

  • Модуль/пространство имен «SBETypeProvider» из единицы компиляции «tmp5CDE» не содержит имен, модуль или тип ' Автомобиль»

  • ссылка типа„SBETypeProvider.Car“в сборе„tmp5CDE“был найден, но тип не может быть найдено в этой сборке

Что я делаю неправильно? На рисунке показано, что тип здесь. Почему я не могу его создать?

Я просмотрел многие провайдеры типов на GitHub и не могу найти ясный пример того, как сгенерировать ProvidedTypeDefinition из другого.

ответ

2

Это не может быть проблемой, но на быстрый взгляд это выглядит как line you linked может быть на самом деле вопрос:

let mTy = ProvidedTypeDefinition(asm, ns, message.Key, Some(typeof<ValueType>), 
         HideObjectMethods = true, IsErased = false) 

Этот тип добавляется к предоставленному типу ty (тот, который будет на самом деле быть записаны во временную сборку), и поэтому не должны иметь сборки и пространства имен.

let mTy = ProvidedTypeDefinition(message.Key, Some(typeof<ValueType>), 
         HideObjectMethods = true, IsErased = false) 

Возможно работать лучше. Сгенерированные типы - это немного черное искусство, но с очень маленькой документацией, так что возможно (возможно?), Что будут другие проблемы, которые вы можете найти.

В общем случае для создания предоставленных типов то, что я обычно делаю, возвращает возвращаемый конструктор как значение, которое затем может быть встроено в код вызова для других свойств/функций с помощью Expr.Call. Это особенно важно для стираемых типов, так как отражение в любом случае не будет работать на них.

+0

Спасибо! Год, этот с неправильной перегрузкой был одним из нескольких вопросов и, вероятно, основным для моего вопроса! Я уже опубликовал еще одну проблему для GitHub StarterPack о структурах. Ваше имя + pic скажет мне, что именно вы являетесь основным спонсором. –

+0

Я теперь построил лучшую ментальную модель ТП после серфинга через большинство известных ТП и с помощью гуру F #. Главной проблемой была перегрузка, но есть так много «тонкостей», как решение сборки. Почему это все еще «черное искусство», как вы говорите !? TP - одна из самых хвалимых, крутых, уникальных и мощных функций F #, но когда дело доходит до новых реализаций - люди теряются. И они действительно теряются * полностью * в начале как слепые котята :) Как улучшить документы? –

Смежные вопросы