How to examine .NET assembly without using reflection - c#

Let's say, we have class Base, and Derived, defined in Base.dll and Derived.dll respectively. Derived is derived from Base (may not be a direct sub-class though)
The problem at hand is, if we have Derived.dll at hand but Base.dll is missing, how to programmatically examine all the types in Derived? e.g. to know what types are available, their accessibility, inheritance relationship, etc
Based on my understanding, reflection (things in System.Reflection namespace) is not an option here because GetTypes() will try to load Base.dll which is not available, thus throw ReflectionTypeLoadException.
In particularly, is this something that can be easily achieved using Roslyn, or some good library?

You're looking for System.Reflection.Metadata, which exposes assembly metadata directly, without loading assemblies via reflection.

For investigate .NET assembly (types, methods etc.) you need to get that from the metadata. Roslyn its not what you are looking for.
Although it's not exactly true, because Roslyn has two types of information about your code, one is nodes and token and the other is symbols. The first don't know about relation info but the second know.
Anyway, you can do it in more than one way. I'll write two of them.
Use Mono.Cecil to open your assembly, get the main module and investigate whatever you want.
var allTypesDefinitaion = ModuleDefinition.ReadModule(assemblyPath).Types;
Use tools like CFF Explorer to investigate the relevant metadata tables. (TypeDef\Ref)

Related

Assembly.GetCustomAttributes still considered best approach?

I want to point to a directory of DLL's and read the attributes of the classes in it. Most classes have a custom attribute with various properties that I want to read.
I have some old code which uses Assembly.GetCustomAttributes
Is this still considered the best approach?
Assembly.GetCustomAttributes gets you attributes for the assembly - which is assemblie's metadata. This are usually place in the AssemblyInfo.cs while they can be placed anywhere.
It should not be confused with class custom attributes - or property/method/field/etc.
If you mean you want to filter out assemblies to look out for by having a custom attribute which identifies such assemblies of interest, then it is a valid approach. However, bear in mind, to read such attributes, assembly first needs to be loaded onto memory.
Reflection is the only way to read custom attributes. Some pseudo custom attributes are reflected on properties of the System.Type class. Assemblies loaded 'normally' cannot be unloaded from an appdomain, so ideally you want to load the assemblies into a reflection only context (there are methods System.Reflection.Assembly.ReflectionOnlyLoad and ReflectionOnlyLoadFrom) so that they may be unloaded when you have your desired information.

Enforcing type visibility between namespaces in C#

I have the idea that it might be useful to enforce type visibility between namespaces rather than assemblies (internal) in C#.
It would seem that such a concept would assist developers working with a codebase, ensuring the correct types are used in places where another internal type supplying similar functionality is available, but would result in "architectural" disadvantages (unwanted dependencies etc).
Do others think this would be useful and is it currently possible? If not why not?
Also, would the concept of preclusions - the ability to specify negative constraints on references between namespaces and / or assemblies be a useful addition to C#?
A type is strongly bound to the assembly in which it is defined. A namespace is not, it can appear in multiple assemblies. System.Configuration for example.
Let's assume for a moment that the metadata format for an assembly would be changed (-1 billion points) to store attributes for a namespace. Those attributes would still have to be stored in an assembly because that's the storage unit for metadata. Now you have to deal with the possibility that the CLR loads another assembly and finds the same namespace but with conflicting attributes. How could it possibly resolve that?
More seriously, how would you prevent external code from simply using the same namespace and attributes to suddenly get access to implementation details that were meant to be private. This completely destroys the value of having the internal keyword.
You could make them public, tag them with a custom attribute, and then add a FxCop rule to check for accesses from the outside of the namespace.
This doesn't securely enforce the restriction and fails when the member is accessed with reflection, but if it's only about policy/codingstyle this should be enough.
I think there is also an existing attribute to hide members from Intellisense which you might use in conjunction with your custom attribute.

How can I prevent the referencing of a certain assembly when running in Mono

I know how to branch the code based on Mono (Type.GetType("Mono.Runtime") != null) but even when the Mono code path is taken, Mono is attempting to load assemblies that would be required by the non-Mono code path. This is not all that surprising, but how do I get around the problem? I have tried putting the call to the non-Mono assembly in a different class, but that didn't help.
The only option to do it directly is Reflection all the way, so far as I can see.
I'd suggest a more roundabout approach: refactor all your code that is dependent on Mono or .NET into separate assemblies, one for each platform - let's call them MA and NA. Make sure that the entire API surface of your classes there is covered by common interfaces, which should be in the 3rd assembly, IA. After that, your main application references IA for interfaces, and uses Reflection just once to load either MA or NA depending on whether it's running on Mono or .NET, and obtain the instance of "top-level factory class". Once there, it just uses normal calls via IA interfaces to instantiate all other objects via that factory and work with them.
Expanding on Pavel's answer you can use a plugin framework to help with the conditionality of loading bits of code that are specific to a platform. You can use Mono.Addins or MS' own open sourced Managed Extensibility Framework known as MEF (http://www.codeplex.com/MEF)
Don't add the reference in the command-line compiler options. If you are using a high level IDE tool then you might have to play with its project settings to effect the same thing.
There are other files that come into play too like AssemblyInfo.cs and might contain instructions about assemblies that you are considering. Also the program might be using types from App.Config (Configuration file) or Web.Config (ASP.NET) / dynamic type loading.
Don't rely for your dependencies on the fact that your code is JITted and that only called code is JITted.
Best is always to assume, that whatever is referenced will be loaded and has to be available.
You user might choose to use AOT, which is Mono's counterpart of NGEN.
Or subtle differences in how newer runtime versions handle things like serialization, remoting, security, reflection, etc. can lead to your references being loaded even your code does not use anything directly. (But the serializer might have pulled all types, which then loaded other assemblies)
Use interfaces or classic inheritance, or maybe events or other means of indirection to load the .Net parts only when they are appropriate. And by hat I mean an assembly that you don't reference but load dynamically.

Sharing dll without adding reference

I have got a dll placed in a shared folder over development server. Is there any way to use that dll without adding reference in my application and without installing the same in GAC.
Thanks in advance.
Assembly asm = Assembly.LoadFrom(path);
See MSDN for late binding, reflection etc.
Small edit: A variable with the keyword "as" is asking for trouble. So "Assembly as" changed to "Assembly asm" should be safer.
You may want to look at the Managed Extensibility Framework or at Assembly.Load... in the base framework.
Why would you want to do this, though? You'd need to call any code within the Assembly via reflection (hence the suggestion that the MEF may be what you're really after).
Yes, it is possible...somehow. Have a look at the Assembly-Class. With it you can load assemblies from a file without knowing what you exactly load.
Using Assembly.LoadFrom would be the only way to have zero references, but you'd still need to share contracts.
What's the problem with adding a reference?
What are you going to do when someone wants to work on a laptop and the WiFi goes down?
Yes,
you can call Assembly.Load() and then make use of Reflection to call into the public interface (lowercase "interface" - what I mean is the methods, fields and properties) exposed by the assembbly.
But in order to do that you need to know what methods to call. It helps if you can be certain that the assembly includes classes that do conform to a known .NET interface.
This idea is the basis for "plug-in" architectures in many tools, where the tool loads any assembly in its "plugin" directory, instantiates classes, casts the result to an ISomething, and then invokes methods via that interface.
I also would read Suzanne Cook's .NET CLR Notes.
http://blogs.msdn.com/suzcook/default.aspx
If this assembly is in a shared folder, you may find that .NET security restrictions stop you working with classes in that assembly in quite the way you'd expect.
Rather than storing on a shared folder, you may want to consider checking in the assembly to your source code repository. (I've seen a "/lib" folder used to good effect for this). Then you can reference the assembly directly.
(There are also repository solutions such as Maven that can more properly control this. However, they don't play well with .NET, unfortunately.)

How Do I Load an Assembly and All of its Dependencies at Runtime in C# for Reflection?

I'm writing a utility for myself, partly as an exercise in learning C# Reflection and partly because I actually want the resulting tool for my own use.
What I'm after is basically pointing the application at an assembly and choosing a given class from which to select properties that should be included in an exported HTML form as fields. That form will be then used in my ASP.NET MVC app as the beginning of a View.
As I'm using Subsonic objects for the applications where I want to use, this should be reasonable and I figured that, by wanting to include things like differing output HTML depending on data type, Reflection was the way to get this done.
What I'm looking for, however, seems to be elusive. I'm trying to take the DLL/EXE that's chosen through the OpenFileDialog as the starting point and load it:
String FilePath = Path.GetDirectoryName(FileName);
System.Reflection.Assembly o = System.Reflection.Assembly.LoadFile(FileName);
That works fine, but because Subsonic-generated objects actually are full of object types that are defined in Subsonic.dll, etc., those dependent objects aren't loaded. Enter:
AssemblyName[] ReferencedAssemblies = o.GetReferencedAssemblies();
That, too, contains exactly what I would expect it to. However, what I'm trying to figure out is how to load those assemblies so that my digging into my objects will work properly. I understand that if those assemblies were in the GAC or in the directory of the running executable, I could just load them by their name, but that isn't likely to be the case for this use case and it's my primary use case.
So, what it boils down to is how do I load a given assembly and all of its arbitrary assemblies starting with a filename and resulting in a completely Reflection-browsable tree of types, properties, methods, etc.
I know that tools like Reflector do this, I just can't find the syntax for getting at it.
Couple of options here:
Attach to AppDomain.AssemblyResolve and do another LoadFile based on the requested assembly.
Spin up another AppDomain with the directory as its base and load the assemblies in that AppDomain.
I'd highly recommend pursuing option 2, since that will likely be cleaner and allow you to unload all those assemblies after. Also, consider loading assemblies in the reflection-only context if you only need to reflect over them (see Assembly.ReflectionOnlyLoad).
I worked out Kent Boogaart's second option.
Essentially I had to:
1.) Implement the ResolveEventHandler in a separate class, inheriting from MarshalByRefObject and adding the Serializable attribute.
2.) Add the current ApplicationBase, essentially where the event handler's dll is, to the AppDomain PrivateBinPath.
You can find the code on github.

Categories

Resources