[rdnzl-devel] Fixed Assembly Resolver Example
Seth Burleigh
seth at tewebs.com
Sun Feb 14 23:47:43 UTC 2010
When attempting to use the import assembly example from
http://common-lisp.net/pipermail/rdnzl-devel/2008-February/000192.html
I was having trouble. Basically, the fullname of the assembly was being
passed in after I had officially loaded the assembly (it happens one
time after attempting to create a new object in the assembly) and it was
then trying to load something like AnAssembly, Culture=Neutral .dll
So here i fixed it and you should do something like this to use it:
(assembly-path! "C:/path/to/assembly/directory/" "/another/directory/")
(install-assembly-resolver)
I took the liberty of making install-assembly-resolver uninstall the
previous assembly resolver if there were any. This is most likely the
desired behavior since you dont want to install the same function each
time.
-------------- next part --------------
;;EXPORT
;;(install-assembly-resolver)
;;(assembly-path! "C:/path/to/assemblies1" ...)
;;automatically uninstalls previous assembly resolver when
;;calling (install-assembly-resolver)
;;FIXES bug in which assembly-name is passed to assembly-resolver
;;in fullname, thus the function attempts to find wrong dll name.
(in-package :rdnzl-user)
;;; Adds additional paths to the search-path used by the
;;; assembly-loader; so that e.g. (load-assembly x) will search for x
;;; not only in the system and application directories, but also in
;;; every directory in *additional-assembly-directories*
;;;
;;; Example:
;;; RDNZL-USER 3 > (load-assembly "AproposGui")
;;; Warning: Returning NULL object from .NET call
;;, NIL
;;; RDNZL-USER 4 > (pushnew (translate-logical-pathname #P"rdnzl:examples;")
;;; *additional-assembly-directories*)
;;; RDNZL-USER 5 > (install-assembly-resolver)
;;; #<RDNZL::CONTAINER System.ResolveEventHandler #xBD6E28>
;;; RDNZL-USER 6 > (load-assembly "AproposGui")
;;; #<RDNZL::CONTAINER System.Reflection.Assembly #xBD7078>
;;;
;;; Alternative method of loading an assembly that doesn't lock the
;;; assembly file:
;;; byte[] asm = File.ReadAllBytes(asmPath);
;;; return Assembly.Load(asm);
(defparameter *additional-assembly-directories* nil)
(defun assembly-path! (&rest args)
(loop for arg in args do(pushnew arg *additional-assembly-directories* :test #'equal))
*additional-assembly-directories*)
(defun assembly-resolver (app-domain resolve-event-args)
(declare (ignore app-domain))
(let ((assembly-name (property resolve-event-args "Name")))
(loop
with parsed-name =
(let ((comma-pos (position #\, assembly-name)))
(if comma-pos (subseq assembly-name 0 comma-pos) assembly-name))
with filename = (make-pathname :name parsed-name :type "dll")
for dir in *additional-assembly-directories*
for dirpath = (if (pathnamep dir) dir (parse-namestring dir))
for path = (merge-pathnames dirpath filename)
when (probe-file path)
do
(let*
((evidence
(property
(invoke "System.Reflection.Assembly" "GetExecutingAssembly")
"Evidence"))
(assembly
(invoke "System.Reflection.Assembly" "LoadFile" (namestring path) evidence)))
(return-from assembly-resolver assembly))
finally (return (make-null-object "System.Reflection.Assembly")))))
(defvar *assembly-resolve-handler* nil)
(defun install-assembly-resolver (&optional (handler #'assembly-resolver))
(let ((my-domain (property "System.AppDomain" "CurrentDomain"))
(assembly-resolve-delegate (new "System.ResolveEventHandler" handler)))
(when *assembly-resolve-handler*
(uninstall-assembly-resolve-handler
*assembly-resolve-handler*)
(setf *assembly-resolve-delegate* assembly-resolve-delegate))
(prog1 assembly-resolve-delegate
(invoke my-domain "add_AssemblyResolve" assembly-resolve-delegate))))
(defun uninstall-assembly-resolve-handler (handler)
(invoke (property "System.AppDomain" "CurrentDomain") "remove_AssemblyResolve" handler)
(setf *assembly-resolve-handler* nil))
More information about the rdnzl-devel
mailing list