Wie für den Zugriff auf private Felder / Methoden / Eigenschaften f # interaktive Verwendung

StackOverflow https://stackoverflow.com/questions/1666767

Frage

F # interactive ist ein leistungsfähiges Entwicklungswerkzeug, wie es erlaubt entweder WinForm oder Wpf Fenster und aufrufen, beliebigen Code in dort auszuführen.

Das gibt einen Weg für ein 'Try-before-you-Code' -Ansatz.

Sehr oft wünsche ich ‚die Grenzen zu brechen‘ explizit und

  • aufrufen private / geschützten Methoden
  • Zugriff / ändern private Felder und Eigenschaften

Gibt es eine Abhilfe dies zu erreichen?

War es hilfreich?

Lösung

FSI stellt keine besondere Unterstützung für diese, aber Sie können Reflexion verwenden, um die Dinge zu tun, die Sie wollen.

open System.Reflection
let field = typeof<MyType>.GetField("fieldName", BindingFlags.NonPublic ||| BindingFlags.Instance)
field.SetValue(myInstance, newVal)

Sie können noch weiter gehen und definieren Methoden oder Betreiber machen dies noch einfacher. Zum Beispiel können Sie F # 's dynamischen Zuweisungsoperator eingerichtet private Felder zuweisen:

let (?<-) o s v = 
  let field = (o.GetType()).GetField(s, BindingFlags.NonPublic ||| BindingFlags.Instance)
  field.SetValue(o,v)

myInstance?fieldName <- newVal (* Note: no quotes around fieldName here *)

Hier einige groben Code öffentliche oder private Felder, Eigenschaften oder Methoden zu lösen. Beachten Sie, dass es viele Möglichkeiten gibt, in denen dies nicht (insbesondere versuchen, es zu verwenden, um auf überladene Methoden nicht funktionieren wird).

open System
open System.Reflection
open Microsoft.FSharp.Reflection

type DynamicHelper =  
  static member MkMethod<'t,'u> (mi:MethodInfo) o : 't -> 'u=
    let typ = typeof<'t>
    fun t -> 
      let args = 
        if (typ = typeof<unit>) then [||]
        else
          if not (FSharpType.IsTuple typ) then [| box t |]
          else
            FSharpValue.GetTupleFields t
      mi.Invoke(o, args) :?> 'u

let (?) (o:'a) s : 'b =
  let ty = o.GetType()
  let field = ty.GetField(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
  if field <> null then field.GetValue(o) :?> 'b
  else
    let prop = ty.GetProperty(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
    if prop <> null then prop.GetValue(o, null) :?> 'b
    else
      let meth = ty.GetMethod(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
      let d,r = FSharpType.GetFunctionElements(typeof<'b>)
      typeof<DynamicHelper>.GetMethod("MkMethod").MakeGenericMethod([|d;r|]).Invoke(null, [| box meth; box o |]) :?> 'b

Mit diesem können Sie dynamisch aufrufen Methoden und Eigenschaften wie zum Beispiel:

let (t:System.Type) = "test"?GetType()?BaseType
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top