2016-08-18 5 views
5

사용하려는 라이브러리가 UWP 응용 프로그램에서만 사용할 수 있으므로 C#에서 UWP (Universal Windows Platform) 응용 프로그램 서비스 공급자를 만들려고합니다.F #에서 UWP 응용 프로그램 서비스를 사용합니다.

그러나 F #에서 위의 UWP 서비스 공급자를 호출하여 라이브러리를 활용해야합니다.

https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service에 따르면 서비스 공급자와 소비자 모두 UWP를 사용하여 C#으로 작성된 경우 (F #은 아직 UWP에서 지원되지 않기 때문에)이 작업을 수행 할 수 있습니다.

제 질문은 F # 프로젝트에서 C#으로 작성된 UWP 앱 서비스를 호출 할 수 있는지 여부입니다. 하나는 UWP C# app 서비스 공급자이고 다른 하나는 F # 콘솔 응용 서비스 소비자 인 두 개의 프로젝트로 솔루션을 만들 수 있습니까?

+0

=> 먼저 세상을해야합니다 :) – Bart

+0

@Bart Windows.Media.Ocr (https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.ocr)은 저의 이해에 따라 세계 최초입니다 - "도서관은 Windows Phone 및 Windows 스토어 앱에서만 강력한 제한 사항입니다. " @ http://blog.a9t9.com/2015/09/ocr-api.html – bugfoot

+1

대신 사용할 클라우드 API가 있습니다. https://ocr.space/OCRAPI – Bart

답변

2

위의 링크 된 다른 게시물의 향상된 코드는 WinRT 비동기 개체를 F # Async<_>에 매핑하여 일부 형식을 훨씬 더 즐겁게 만듭니다.

open System.Reflection 

type Asyncifier() = 
    static let winrtExts = System.Type.GetType("System.WindowsRuntimeSystemExtensions, System.Runtime.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 
    static let asTask = winrtExts.GetMethods() |> Seq.find(fun m -> m.Name = "AsTask" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length = 1 && m.ReturnType.IsGenericType) 
    static member FromTask<'t,'u>(t:System.Threading.Tasks.Task<'t>) = 
     async { 
      let! t = Async.AwaitTask t 
      return box t :?> 'u 
     } 
    static member FromIAsyncObjThrough<'t>(argTy, o) : Async<'t> = 
     typeof<Asyncifier>.GetMethod("FromTask").MakeGenericMethod(argTy, typeof<'t>).Invoke(null, [| asTask.MakeGenericMethod(argTy).Invoke(null, [|o|]) |]) :?> _ 

let getWindowsType (name:string) = 
    let ns = let parts = name.Split('.') in parts.[0] + "." + parts.[1] 
    System.Type.GetType(sprintf "%s, %s, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime" name ns) 

let IAsyncOperation = getWindowsType "Windows.Foundation.IAsyncOperation`1" 

let (?) (o:obj) s : 'a = 
    let rec build ty args = 
     if Reflection.FSharpType.IsFunction ty then 
      let dom, rng = Reflection.FSharpType.GetFunctionElements ty 
      let mkArgs = 
       if dom = typeof<unit> then 
        if Reflection.FSharpType.IsFunction rng then failwith "Unit as non-final argument in curried definition?" 
        fun _ -> args 
       else 
        fun arg -> arg::args 
      Reflection.FSharpValue.MakeFunction(ty, fun o -> build rng (mkArgs o)) 
     else 
      let rcvr,ty,flags = 
       match o with 
       | :? System.Type as ty -> null,ty,BindingFlags.Static 
       | _ -> o,o.GetType(),BindingFlags.Instance 
      let flags = flags ||| BindingFlags.Public 
      let meth = 
       if Reflection.FSharpType.IsFunction typeof<'a> then 
        query { 
         for m in ty.GetMethods(flags) do 
         where (m.Name = s) 
         where (m.GetParameters().Length = args.Length) 
         exactlyOne 
        }      
       else 
        ty.GetProperty(s, flags).GetGetMethod() 
      let result = meth.Invoke(rcvr, args |> List.toArray) 
      let resultTy = 
       let rec resultTy ty = 
        if Reflection.FSharpType.IsFunction ty then Reflection.FSharpType.GetFunctionElements ty |> snd |> resultTy 
        else ty 
       resultTy typeof<'a> 
      let (|GenericTypeInstance|_|) (genTy:System.Type) (ty:System.Type) = 
       if ty.IsGenericType && ty.GetGenericTypeDefinition() = genTy then Some (ty.GetGenericArguments()) 
       else None 
      let asyncTy = typedefof<Async<_>> 
      match meth.ReturnType, resultTy with 
      | GenericTypeInstance IAsyncOperation [|winRtTy|], GenericTypeInstance asyncTy [|returnTy|] -> 
       // unwrap to F# async 
       typeof<Asyncifier>.GetMethod("FromIAsyncObjThrough").MakeGenericMethod(returnTy).Invoke(null, [|winRtTy; result|]) 
      | _ -> result 
    build typeof<'a> [] :?> 'a 

그리고 여기 당신이 OCR 작업을 수행하는 데 사용할 수 있습니다 방법은 다음과 같습니다

"내가 사용하고자하는 라이브러리가 UWP 응용 프로그램 내에서만 사용할 수 있기 때문에"
let Language = getWindowsType @"Windows.Globalization.Language" 
let OcrEngine = getWindowsType "Windows.Media.Ocr.OcrEngine" 
let BitmapDecoder = getWindowsType "Windows.Graphics.Imaging.BitmapDecoder" 
let StorageFile = getWindowsType "Windows.Storage.StorageFile" 

let enUs = Language.GetConstructor([|typeof<string>|]).Invoke([|"en-US"|]) 
let engine : obj = OcrEngine?TryCreateFromLanguage enUs 

let getTextAsync (path:string) : Async<string> = async { 
    let! file = StorageFile?GetFileFromPathAsync path 
    let! stream = file?OpenReadAsync() 
    let! decoder = BitmapDecoder?CreateAsync stream 
    let! bitmap = decoder?GetSoftwareBitmapAsync() 
    let! result = engine?RecognizeAsync bitmap 
    return result?Text 
} 
+0

감사합니다. @kvb, 그것은 멋져 보입니다 :-) 주말에 확인합니다! – bugfoot

+0

@kvb 어떻게 든 기능을 지정해야합니까? Bluetooth 장치 참조를 검색하는 것과 같은 특정 일을 할 때 프로그램이 멈추는 경향이 있습니다. –

+0

데스크톱 앱에서 실행중인 경우 (예 : F # 대화식) 적용해야한다고 생각하지 않습니다. 어쩌면 간단한 질문과 함께 새로운 질문을 게시 할 수 있습니까? – kvb

관련 문제