Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- open System
- open System.Linq
- open System.Net
- open System.Reflection
- open System.Reflection.Emit
- open System.Collections.Generic
- [<AttributeUsage(AttributeTargets.Class, AllowMultiple = false)>]
- type public LoggingAttributeAttribute (t : Type) =
- inherit Attribute()
- member public this.AttachedType
- with get() = t
- [<LoggingAttribute(typeof<MyClass>)>]
- type public MyClass () =
- class
- abstract member DoStuff : unit -> string
- default this.DoStuff () =
- "hello world"
- end
- type ExtendedMyClassDoStuffDelegate =
- delegate of unit -> string
- (*
- let GenerateLogging (attrs : LoggingAttributeAttribute seq) =
- let types = Seq.map (fun (attr : LoggingAttributeAttribute) -> attr.AttachedType) attrs
- let asmName = new AssemblyName "myAssembly"
- let ab = AppDomain.CurrentDomain.DefineDynamicAssembly (asmName, AssemblyBuilderAccess.Run)
- let mb = ab.DefineDynamicModule asmName.Name
- for t in types do
- let name = t.Name
- let methods = t.GetMethods (BindingFlags.Public ||| BindingFlags.DeclaredOnly ||| BindingFlags)
- let tb = mb.DefineType ("Extended" + name, TypeAttributes.Public, t)
- let cb = tb.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Array.empty)
- let cbIl = cb.GetILGenerator ()
- cbIl.Emit OpCodes.Ldarg_0
- cbIl.Emit (OpCodes.Call, typeof<MyClass>.GetConstructor Type.EmptyTypes)
- cbIl.Emit OpCodes.Ret
- for m in methods do
- let methodName = m.Name
- let mb = tb.DefineMethod (methodName, MethodAttributes.Public ||| MethodAttributes.HideBySig ||| MethodAttributes.Virtual ||| MethodAttributes.NewSlot, m.
- 0
- *)
- [<EntryPoint>]
- let main args =
- let attrs = [|
- for x in (Attribute.GetCustomAttributes(Assembly.GetEntryAssembly(), typeof<LoggingAttributeAttribute>))
- do yield x :?> LoggingAttributeAttribute
- |]
- let asmName = new AssemblyName "myAssembly"
- let ab = AppDomain.CurrentDomain.DefineDynamicAssembly (asmName, AssemblyBuilderAccess.Run)
- let mb = ab.DefineDynamicModule asmName.Name
- let tb = mb.DefineType ("ExtendedMyClass", TypeAttributes.Public, typeof<MyClass>)
- let cb = tb.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Array.empty)
- let cbIl = cb.GetILGenerator ()
- cbIl.Emit OpCodes.Ldarg_0
- cbIl.Emit (OpCodes.Call, typeof<MyClass>.GetConstructor Type.EmptyTypes)
- cbIl.Emit OpCodes.Ret
- let mbDoStuff =
- tb.DefineMethod ("DoStuff", MethodAttributes.Public ||| MethodAttributes.HideBySig ||| MethodAttributes.Virtual ||| MethodAttributes.NewSlot, typeof<string>, Type.EmptyTypes)
- let ilDoStuff = mbDoStuff.GetILGenerator ()
- ilDoStuff.Emit OpCodes.Ldarg_0
- ilDoStuff.Emit(OpCodes.Ldstr, "Calling base `DoStuff'")
- ilDoStuff.Emit (OpCodes.Call, typeof<Console>.GetMethod ("WriteLine", [| typeof<string> |]) )
- ilDoStuff.Emit (OpCodes.Callvirt, typeof<MyClass>.GetMethod "DoStuff")
- ilDoStuff.Emit OpCodes.Ret
- let myDynamicType = tb.CreateType ()
- let extendedMyClass = Activator.CreateInstance myDynamicType
- let del = Delegate.CreateDelegate (typeof<ExtendedMyClassDoStuffDelegate>, extendedMyClass, "DoStuff")
- let extendedMyClassDoStuff = del :?> ExtendedMyClassDoStuffDelegate
- let myClass = new MyClass ()
- [myClass.DoStuff; extendedMyClassDoStuff.Invoke]
- |> List.map (fun del -> del() )
- |> List.iter (fun str -> printfn "%s" str)
- 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement