Я хотел бы сгенерировать тип со статическими функциями, который затем я могу использовать в функциях, которые становятся котировками, используя атрибут ReflectedDefinition. Мне представляется удобным способом перевести что-то в типы FSharp, используя FSharp для составления домена функций и типов, и выплескивать скомпилированный код обратно в его родную форму, получив преимущество проверки типов, VS intellisense, функций более высокого порядка и т.д. Для того, чтобы попробовать и начать работу у меня есть этот провайдер типа, в основном от копирования> вставило из различных статейМожет ли используемый тип использоваться в цитате - возникают ли вызовы TypeProvider в функциях ReflectedDefinition?
[<TypeProvider>]
type CSoundTypeProvider(config: TypeProviderConfig) as this =
inherit ProvidedTypes.TypeProviderForNamespaces()
let namespaceName = "TestNamespace"
let thisAssembly = Assembly.GetExecutingAssembly()
// config.
let intType = typeof<int>
let providedParam = ProvidedTypes.ProvidedParameter("prm", intType)
let providedFunction = ProvidedTypes.ProvidedMethod("TestMethod", [providedParam], intType, IsStaticMethod=true
, InvokeCode = fun args ->
// The 'args' parameter represents expressions that give us access to the
// instance on which the method is invoked and other parameters (if there are more)
let instance = args.[0]
// Now we can return quotation representing a call to MethodInfo 'p' with 'instance'
instance)
let csoundProvidedWrapper = ProvidedTypes.ProvidedTypeDefinition(thisAssembly, namespaceName, "TestType", None)
do csoundProvidedWrapper.AddMember(providedFunction)
do this.AddNamespace(namespaceName, [csoundProvidedWrapper])
и тестирование его с этим отражено определением:
[<ReflectedDefinition>]
let myfn i j =
let k = i * j
let x = k + 2
let f = TestNamespace.TestType.TestMethod k
let ret = f + 2
ret
Я разбор отраженное определение следующим образом:
<@ myfn @> |> println
Println является функцией (копируется из другой статьи), который имеет многие из активных шаблонов для синтаксического анализа котировок, как Patterns.Call (None, DerivedPatterns.MethodWithReflectedDefinition (п), expList), который получает меня дерево выгрузки всего кода, за исключением для предоставленного статического метода. Является ли то, что я пытаюсь сделать, даже возможно? Если это так, что активный шаблон я вероятно пропустил из моей Println функции здесь:
let println expr =
let rec print expr = match expr with
| Patterns.Application(expr1, expr2) ->
// Function application.
print expr1
printf " "
print expr2
| Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList) ->
print n
| Patterns.Call(exprOpt, methodInfo, exprList) ->
// Method or module function call.
match exprOpt with
| Some expr -> print expr
| None -> printf "%s" methodInfo.DeclaringType.Name
printf ".%s(" methodInfo.Name
if (exprList.IsEmpty) then printf ")" else
print exprList.Head
for expr in exprList.Tail do
printf ","
print expr
printf ")"
| DerivedPatterns.Int32(n) ->
printf "%d" n
| Patterns.Lambda(param, body) ->
// Lambda expression.
printf "fun (%s:%s) -> " param.Name (param.Type.ToString())
print body
| Patterns.Let(var, expr1, expr2) ->
// Let binding.
if (var.IsMutable) then
printf "let mutable %s = " var.Name
else
printf "let %s = " var.Name
print expr1
printf " in "
print expr2
| Patterns.PropertyGet(_, propOrValInfo, _) ->
printf "%s" propOrValInfo.Name
| DerivedPatterns.String(str) ->
printf "%s" str
| Patterns.Value(value, typ) ->
printf "%s" (value.ToString())
| Patterns.Var(var) ->
printf "%s" var.Name
| _ -> printf "%s" (expr.ToString())
print expr
Если я не могу это сделать, какой подход вы рекомендовали бы для создания определений FSharp, что я могу использовать в кавычках? На меня в значительной степени повлиял проект FunScript, но он надеялся избежать шага, на котором, по-видимому, каждое определение дескриптора должно быть скомпилировано в отдельную DLL.
Большое спасибо за то, что нашли время, чтобы объяснить это. Я не оценил, что определение ** InvokeCode ** так важно. Я только пытаюсь сгенерировать типы настолько же глубокие, как открытый интерфейс провайдера типов, отсюда и немой код в моем примере. В свете этой информации, возможно, создание провайдера типов является излишним для того, что я действительно пытаюсь сделать, что представляет собой интерфейс. –