2016-08-18 7 views
5

से यूडब्लूपी ऐप सेवा का उपभोग करें मुझे सी # में यूनिवर्सल विंडोज प्लेटफ़ॉर्म (यूडब्लूपी) ऐप सेवा प्रदाता बनाने का सहारा लिया गया है क्योंकि लाइब्रेरी का उपयोग करना चाहता हूं केवल यूडब्ल्यूपी ऐप्स के भीतर ही उपलब्ध है।एफ #

हालांकि, मुझे एफ # में एक (कंसोल) एप्लिकेशन लिखना होगा जो पुस्तकालय का लाभ लेने के लिए उपरोक्त यूडब्ल्यूपी सेवा प्रदाता को कॉल करेगा।

https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service के अनुसार यह किया जा सकता है यदि सेवा प्रदाता और उपभोक्ता दोनों यूडब्ल्यूपी का उपयोग कर सी # लिखे गए हैं (चूंकि एफ # अभी तक यूडब्ल्यूपी में समर्थित नहीं है)।

मेरा सवाल यह है कि क्या मैं एक एफ # परियोजना से सी # में लिखी गई यूडब्ल्यूपी ऐप सेवा को कॉल कर सकता हूं? क्या मैं दो परियोजनाओं के साथ समाधान बना सकता हूं, जिनमें से एक यूडब्ल्यूपी सी # ऐप सेवा प्रदाता है और दूसरा एफ # कंसोल ऐप सेवा उपभोक्ता है?

+0

"के बाद से पुस्तकालय मैं का उपयोग करना चाहते UWP ऐप्स के भीतर से ही उपलब्ध है" => पहले एक दुनिया होना चाहिए:) – Bart

+0

@ बार्ट विंडोज़। मीडिया.ओसीआर (https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.ocr) मेरी समझ के अनुसार पहली ऐसी दुनिया है - "लाइब्रेरी काम करता है केवल विंडोज फोन और विंडोज स्टोर ऐप के साथ, जो एक मजबूत सीमा है। " @ http://blog.a9t9.com/2015/09/ocr-api.html – bugfoot

+1

इसके बजाय उपयोग करने के लिए क्लाउड एपीआई है: 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 

और यहाँ कैसे आप ओसीआर करने के लिए इसका इस्तेमाल करते हैं कर सकते हैं:

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

धन्यवाद @ केवीबी, यह शानदार लग रहा है :-) सप्ताहांत के दौरान जांच करेगा! – bugfoot

+0

@kvb क्या मुझे किसी भी तरह की क्षमताओं को निर्दिष्ट करने की आवश्यकता है? जब मैं कुछ चीजें करता हूं, तो ब्लूटूथ डिवाइस संदर्भ पुनर्प्राप्त करने का प्रयास करने पर प्रोग्राम लटकता रहता है। –

+0

यदि आप डेस्कटॉप ऐप से चल रहे हैं (उदा। एफ # इंटरएक्टिव) तो मुझे नहीं लगता कि इसे लागू करना चाहिए। शायद सरलीकृत रेपो के साथ एक नया सवाल पोस्ट करें? – kvb