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.
Related
I want to facade or proxy a library's implemented attribute.
for example the property mapping attributes.
I want to control which of the libraries attributes to be used in project.
some kind of a DI or Module control.
Is there an easy way to achieve it without using reflection?
something to transfer these two types of attributes into one:
[MapsFromAndToProperty(typeof(fooClass), nameof(fooClass.PropertyName))]
and
[AdaptMember(name)]
into
[MyAttributeToControlWhichOneToUse(typeof(fooClass), nameof(fooClass.PropertyName))]
And Thank you for your attention.
Any help would be appreciated.
As noted in the comments, it is not possible to alter attributes in the general case. This is simply because attributes are effectively part of the assembly metadata and doing what you want means to change that assembly metadata.
There are two ways how this could potentially work, though:
You do change the assembly metadata. Here, you are in the realm of aspect-oriented programming. You could try to create an aspect e.g. based on PostSharp that unrolls your MyAttributeToControlWhichOneToUse attribute into the required attributes at compile-time. This solution is independent of the way how the attributs are read, but requires changes to the build infrastructure.
You alter the way how the attributes are loaded. MEF is an example that does that for its convention-based programming model that effectively emulates attributes on the conventional classes by altering the way how attributes are retrieved. This only works, if foreseen in the lib that reads the properties (and honestly, I have never seen anybody else than MEF to do that).
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)
This may be a long shot, but the flexibility of .NET never ceases to amaze me, so here goes.
I'm developing an MVC application that needs to search through a set of assemblies for class types that are derived from a common base class.
i.e. I have several assemblies that have activity types that are all derived from ActivityBase. These assemblies will be placed in a specific directory. They're kinda like plugins. Since they will need to be loaded dynamically at runtime, they will also need to be accompanied by some dependencies (unless I can figure out a convenient way to separate them, feel free to chime in on this as well.)
I have code that will iterate through all of the .DLL files in this directory, load the assembly, and iterate through all of the types in the assembly to find ones that are derived from ActivityBase.
This works fine. However, I would like to avoid loading and searching through the assemblies that do not have activities, because some of the dependencies have thousands of types and it becomes a performance problem.
So I guess my question is, other than a file naming convention, is there any way to "decorate" or mark an assembly with some type of data that would indicate that it is an activity assembly, that can be easily automated at build time and easily read at runtime?
Any other suggestions for handling this problem are also welcome.
You can implement your own assembly attribute:
[AttributeUsage(AttributeTargets.Assembly)]
public class ActivityAssemblyAttribute : Attribute
{
}
Then decorate necessary assembly with this attribute:
[assembly: ActivityAssemblyAttribute()]
And, when needed, just check whether the assembly under question is decorated with this attribute:
ActivityAssemblyAttribute attribute = null;
object[] attributes = assembly.GetCustomAttributes(typeof(ActivityAssemblyAttribute), false);
if (attributes.Length > 0)
{
attribute = attributes[0] as ActivityAssemblyAttribute;
}
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.
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.