Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / July 2007

Tip: Looking for answers? Try searching our database.

Reflection across all assemblies

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Tim Hardy - 23 Jun 2007 00:21 GMT
I've been trying to reflect across all assemblies in the running application
at Application_Start, but I've been having trouble developing a consistent
mechanism.  I basically just need to look for all classes that derive from a
certain class, as well as classes that contain a custom attribute.  

AppDomain.CurrentDomain.GetAssemblies() does not always return all of the
app's assemblies.  Sometimes it only returns about half of the assemblies,
which is very frustrating.

Another route I've tried is manually loading all the assemblies in the app's
bin folder and reflecting through those.  The problem with this approach is
that it leaves all those extra assemblies hanging out in memory, when all I
needed to do was reflect through them, not execute anything on them.  The app
will be using shadow copies of all the assemblies from some temporary folder,
meaning duplicates will just be wasting memory.  I've tried loading them into
a temporary app domain, but I get security errors trying to load the dll's
from the bin folder into the temp domain (for asp.net app).

Basically, I just need a "best practice" that is consistent and dependable
for reflecting through ALL assemblies that an application uses that will work
for both web and win apps.

Thanks,
Tim
Steven Cheng[MSFT] - 25 Jun 2007 07:26 GMT
Hi Tim,

From your description, you're looking for an approach to loop through all
the assembies used in an .NET framework based application(both web and
winform), correct?

As for the AppDomain.GetAssemblies() method you mentioned, it will only
return those assemblies that has been loaded into the AppDomain's execution
context. However, if you call it at the very begining(intialize stage) of
application, since many referenced assemblies may haven't been loaded yet,
you'll miss them through this approach.  

I think a reasonable approach should work as below:

** you first get the reference of the executing assembly

** use "Assembly.GetReferencedAssemblies" method to get a list of all the
referenced assemblies of the current executing assembly(for most
application, the root main exe assembly should statically referenced most
required assemblies at compile time).

http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.getrefer
encedassemblies.aspx

** After get a list of assemblies(Actually the AssemblyName list), you can
choose to load them and inspect into it or not. If you only want to reflect
types in it, I suggest you use the "Assembly.ReflectionOnlyLoad" method to
load the assembly into "Reflection ONly context". This is a new feature for
you to inspect type/assemblies in a lightweight context(do not need all the
expensive context info when you actually executing code of the target
assemblies)

#How to: Load Assemblies into the Reflection-Only Context  
http://msdn2.microsoft.com/en-us/library/ms172331.aspx

** You can also recursively find the referenced dependency assemblies from
the first List get from the intial executing assembly

Through this approach, you can at least get all those dependency assemblies
you explicitly referenced at design-time/compile time. The only problem is
that if you'll load some assemblies dynamically in code, they won't appear
in the assemblies' static reference list.

In addition, for ASP.NET 2.0 application, you may encounter further problem
since ASP.NET 2.0 application use dynamic compilation and by default page
types may be compiled into multiple temporary assemblies, it is difficult
to locate them from a single central root assembly.  However, ASP.NET 2.0
also provide you approach to manually precompile the entire web
application(through "publish website" or "web deployment project"). Thus,
you can still make most page stuff be compiled into some central assemblies
and you can call reflection against those precompiled assemblies.

Just some of my understanding and suggestion. If you have any further
questions or anything unclear, please feel free to post here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================
   

This posting is provided "AS IS" with no warranties, and confers no rights.
Tim Hardy - 25 Jun 2007 15:58 GMT
That is very helpful, but I've got one remaining hurdle to overcome.  The
code that will reflect across all assemblies is not in the "root" assembly,
therefore GetExecutingAssembly() just returns the assembly containing the
reflecting code.  I need a way to get the root assembly, or the assembly that
kicked everything off.  In this case, it would be the assembly of the web
application containing this common library.  In other cases, it could be a
WinForm containing this common library.

Thank you very much, we're close.
Tim Hardy - 25 Jun 2007 17:49 GMT
I've tried the GetEntryAssembly() method, but that doesn't work for an
ASP.NET application - it returns null.  I've also tried
Process.GetCurrentProcess().MainModule, but that just returns the aspnet
worker process.  

I'm having trouble finding my web application's root assembly
programmatically.  Is there any way to do this?  Surely there's something
special or unique about the web application's root dll.  At some point, the
framework has to load all the referenced assemblies for this dll.
Steven Cheng[MSFT] - 27 Jun 2007 09:26 GMT
Thanks for your reply Tim,

I'm afraid the difficult point here is for the ASP.NET 2.0 web application,
it use dynamic compilation, all the page assemblies are compiled at runtime
and may result to multiple dynamic asssemblies. And unlike winform
application which has an exe image as the entry assembly(central root),
ASP.NET application process is started by IIS server and will dynamically
load the necessary page assemblies for processing request, therefore, you
can not get a central root assembly.  

So far I haven't found any good means that will help us get all the page
assemblies(which will be dynamically generated on-demand) at the
startup/initialize stage of ASP.NET 2.0 application.  One possible
approach, is use the Web Deployment project to customize the precompile of
your ASP.NET 2.0 Web site, this can help make the single (or limited number
of) output assemblies. Thus, you can perform reflection and probing against
those precompiled assmblies:

#Visual Studio 2005 Web Deployment Projects
http://msdn2.microsoft.com/en-us/asp.net/aa336619.aspx

How do you think? BTW, would you provide some further info on why you will
have to get all the referenced or loaded assmblies of a running application?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
   

This posting is provided "AS IS" with no warranties, and confers no rights.
Tim Hardy - 10 Jul 2007 22:00 GMT
I forgot to answer why I'm doing this.  We use Reflection in our app to make
things easier on developers through attribute-based programming.  We slap
attributes on things, then read those at run-time to remove tedious things
from the developer.

This is great, but it costs us in performance, so we've decided to use
run-time code generation to have our cake and eat it to.  We read those exact
same attributes on AppStart, and generate and compile very static, yet very
fast code to do the same things that we were using dynamic invocation, etc to
do before.  For instance, what used to be a method.Invoke() is now a switch
statement with a typed method call.  Or what used to be a complicated series
of state persistence and restoration calls based on property attributes, is
now just a typed Persist() and Restore() method for every class that needs
them.

I need all that reflection at AppStart, so I can generate all that tedious
code that we used to write by hand.
Steven Cheng[MSFT] - 12 Jul 2007 10:25 GMT
Hi Tim,

Glad to hear from you and thanks for your followup and share the your
current implementation to us.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead

This posting is provided "AS IS" with no warranties, and confers no rights.
Damien - 27 Jun 2007 15:43 GMT
> I've tried the GetEntryAssembly() method, but that doesn't work for an
> ASP.NET application - it returns null.  I've also tried
[quoted text clipped - 5 lines]
> special or unique about the web application's root dll.  At some point, the
> framework has to load all the referenced assemblies for this dll.

Surely in this case you can combine your initial idea and Steven's.
Start your list of assemblies to investigate by filling it with
GetAssemblies() (the root assembly is *bound* to be in this list), and
then use GetReferencedAssemblies/loading for reflection only, to
complete the list of assemblies to investigate.

Damien
Tim Hardy - 10 Jul 2007 21:52 GMT
I'm going to have to use a config value to determine what the "root assembly"
is for web applications, but that will allow me to do the above.

In the future, it would be nice if the framework provided us a way to get
the main application's assembly, so I can then find out all it's references.
Damien - 11 Jul 2007 07:53 GMT
> I'm going to have to use a config value to determine what the "root assembly"
> is for web applications, but that will allow me to do the above.
>
> In the future, it would be nice if the framework provided us a way to get
> the main application's assembly, so I can then find out all it's references.

I think the problem is, for ASP.Net, that there's not a single
"blessed" "root assembly" - You could have a web.config that installs
several modules and several handlers, all from different assemblies,
plus the assembly that contains the code-behind for the default page
(as defined in IIS) for the application - I wouldn't know which of
these assemblies would be the "root assembly". So I think in this
case, you're correct that you'll have to store something in config if
there's something special about one of these assemblies.

Damien

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.