I have 2 projects in the solution. Project1UI references Project2Reports
Project1UI:
MainForm.cs
Project2Reports:
BaseReport.cs // all classes below inherit from it
Report1.cs
Report2.cs
Report3.cs
From Project1UI, how can I find all the classes that inherit from BaseReport? The project1UI already references the 2nd assembly - is there a way to do it without manually loading the 2nd assembly manually (e.g. Assembly.Load) since it's already loaded.
You have to process all the types in the assembly and look for the types that implement it.
You can use something like that (written by hand right now, it may contains errors).
foreach (Type type in Assembly.GetAssembly(typeof(BaseReport)).GetTypes())
{
if (type != typeof(BaseReport) && typeof(BaseReport).IsAssignableFrom(type))
{
// we found a type, we can store it somewhere, for example, in a list and our list in a static readonly field for fast lookup in the future.
myreports.Add(type);
}
}
You can also process all the loaded assemblies.
This however is not the best way to do that, is complicated, quite obscure and quite hard to understand.
I would use a simple factory class that will give you the instance of your report as requested, when you add a report, add it through a simple .Add call.
Related
Currently I am working on a project in C# where I have to implement reflection. I have created a WPF application with a GUI. This GUI contains a
combobox which contains all the classnames that implement a specific interface. The classes with the displayed classnames live in the same solution.
Next to the combobox is a button to refresh the content in the combobox. However, when I run my application, modify a classname that implements the interface, and
click on that refresh button the changes don't show up in the combobox. For example, when I change a classname it should display the new classname in stead of the old one.
I have extracted this part of my project to test it in an empty console application. Here I have an interface that is implemented by the classes
QuickSortAlgorithm, DynamicSortAlgorithm and MergeSortAlgorithm. Next I wrote the following, straight forward code, in my main class.
public static List<string> AlgoList = new List<string>();
static void Main(string[] args) {
RefreshAlgorithms();
Print();
Console.WriteLine("\nChange a classname and press a key \n");
Console.ReadKey();
Print();
Console.WriteLine("\nPress a key to exit the program \n");
Console.ReadKey();
}
private static void RefreshAlgorithms() {
AlgoList.Clear();
Type AlgorithmTypes = typeof(IAlgorithms);
foreach (var type in Assembly.GetCallingAssembly().GetTypes()) {
if (AlgorithmTypes.IsAssignableFrom(type) && (type != AlgorithmTypes)) {
AlgoList.Add(type.Name);
}
}
}
private static void Print() {
Console.WriteLine("Algorithm classes:");
foreach (var Algo in AlgoList) {
Console.WriteLine(Algo);
}
}
When I run the application is see the classnames QuickSortAlgorithm, DynamicSortAlgorithm and MergeSortAlgorithm printed. However if I change the name of the, for example,
QuickSortAlgorithm class to QuickSortAlgorithmmmmm I would expect it to print QuickSortAlgorithmmmmm once I press a key. However this is not the case and the name
QuickSortAlgorithm is still being displayed.
I get the feeling that I overlook something in the concept of reflection. Can this even be done after building the solution? If I understood correctly this concept makes it possible to implement changes on runtime. I know that
it will make my application much slower but I'm really eager to learn more about this concept. If one can explain me what I'm doing wrong I would be very happy.
That unfortunately does not work. When your assembly gets loaded, it will stay loaded as it is, changes only applying when you restart your application.
If you are using .NET Framework you can create a new AppDomain and load your assembly into this AppDomain. When you are done, you can unload the AppDomain and with it your assembly. That you can do multiple times in a running application.
void RefreshAlgorithms()
{
var appDomain = AppDomain.CreateDomain("TempDomain");
appDomain.Load(YourAssembly);
appDomain.DoCallback(Inspect);
AppDomain.Unload(appDomain);
}
void Inspect()
{
// This runs in the new appdomain where you can inspect your classes
}
Be careful though, as working with AppDomains has caveats, such as the need to use remoting when communicating with the AppDomain.
In .NET Core there is no such way available, as far as I know
Once you load a compiled .NET assembly into your application, you can't make further changes to the types in that assembly without restarting and rebuilding the application. If this were allowed, then it could lead to all kinds of weird behavior. For example, imagine if the application had a List<Foo> populated with 3 foos and then Foo.Id were changed from an int to a string. What should happen to that live data?
However, if your application doing the reflecting is different than the assembly being reflected over, it is possible to set things up such that you can watch for changes to that assembly file and re-do your reflection. The key is to abandon System.Reflection (which only works on loaded assemblies) and instead use the Mono.Cecil library.
Cecil reads in the assembly metadata without loading the code into the application, so it works well for the "reflection-only" use-case. Of course, what it can't do is actually invoke the code. The Cecil API contains many similarities to System.Reflection. For example:
var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(Path.Combine(projectDirectory, "bin", "Debug", "Something.dll"));
var controllerTypes = assembly.MainModule.Types.Where(t => t.BaseType?.FullName == "System.Web.Mvc.Controller")
.ToArray();
Another note is that .NET Framework (not .NET Core) contains the notion of AppDomains which can be loaded an unloaded. These act like .NET "sub-processes" within the one process and have rules about what can cross their boundaries. If you really need to both reload code and execute it, then this could be a solution.
Another option could be the Roslyn scripting API, which would work well if you want to dynamically load and execute source code (vs. compiled assemblies).
It looks like you're overlooking one small step: building your code. Once you rename the class to QuickSortAlgorithmmmm, you need to save and build that assembly.
Doing so will recreate the assembly (assuming your application doesn't have an open handle on it). After that, clicking the refresh button should show the new name.
If you can't reload the assembly because it has your GUI code in it too (which is running), you may want to separate out the classes that implement the interface into their own assembly, potentially build that separately, and copy it over into a directory where your app can find it (eg. in a Plugins directory).
Currently I am working on a project in C# where I have to implement reflection. I have created a WPF application with a GUI. This GUI contains a
combobox which contains all the classnames that implement a specific interface. The classes with the displayed classnames live in the same solution.
Next to the combobox is a button to refresh the content in the combobox. However, when I run my application, modify a classname that implements the interface, and
click on that refresh button the changes don't show up in the combobox. For example, when I change a classname it should display the new classname in stead of the old one.
I have extracted this part of my project to test it in an empty console application. Here I have an interface that is implemented by the classes
QuickSortAlgorithm, DynamicSortAlgorithm and MergeSortAlgorithm. Next I wrote the following, straight forward code, in my main class.
public static List<string> AlgoList = new List<string>();
static void Main(string[] args) {
RefreshAlgorithms();
Print();
Console.WriteLine("\nChange a classname and press a key \n");
Console.ReadKey();
Print();
Console.WriteLine("\nPress a key to exit the program \n");
Console.ReadKey();
}
private static void RefreshAlgorithms() {
AlgoList.Clear();
Type AlgorithmTypes = typeof(IAlgorithms);
foreach (var type in Assembly.GetCallingAssembly().GetTypes()) {
if (AlgorithmTypes.IsAssignableFrom(type) && (type != AlgorithmTypes)) {
AlgoList.Add(type.Name);
}
}
}
private static void Print() {
Console.WriteLine("Algorithm classes:");
foreach (var Algo in AlgoList) {
Console.WriteLine(Algo);
}
}
When I run the application is see the classnames QuickSortAlgorithm, DynamicSortAlgorithm and MergeSortAlgorithm printed. However if I change the name of the, for example,
QuickSortAlgorithm class to QuickSortAlgorithmmmmm I would expect it to print QuickSortAlgorithmmmmm once I press a key. However this is not the case and the name
QuickSortAlgorithm is still being displayed.
I get the feeling that I overlook something in the concept of reflection. Can this even be done after building the solution? If I understood correctly this concept makes it possible to implement changes on runtime. I know that
it will make my application much slower but I'm really eager to learn more about this concept. If one can explain me what I'm doing wrong I would be very happy.
That unfortunately does not work. When your assembly gets loaded, it will stay loaded as it is, changes only applying when you restart your application.
If you are using .NET Framework you can create a new AppDomain and load your assembly into this AppDomain. When you are done, you can unload the AppDomain and with it your assembly. That you can do multiple times in a running application.
void RefreshAlgorithms()
{
var appDomain = AppDomain.CreateDomain("TempDomain");
appDomain.Load(YourAssembly);
appDomain.DoCallback(Inspect);
AppDomain.Unload(appDomain);
}
void Inspect()
{
// This runs in the new appdomain where you can inspect your classes
}
Be careful though, as working with AppDomains has caveats, such as the need to use remoting when communicating with the AppDomain.
In .NET Core there is no such way available, as far as I know
Once you load a compiled .NET assembly into your application, you can't make further changes to the types in that assembly without restarting and rebuilding the application. If this were allowed, then it could lead to all kinds of weird behavior. For example, imagine if the application had a List<Foo> populated with 3 foos and then Foo.Id were changed from an int to a string. What should happen to that live data?
However, if your application doing the reflecting is different than the assembly being reflected over, it is possible to set things up such that you can watch for changes to that assembly file and re-do your reflection. The key is to abandon System.Reflection (which only works on loaded assemblies) and instead use the Mono.Cecil library.
Cecil reads in the assembly metadata without loading the code into the application, so it works well for the "reflection-only" use-case. Of course, what it can't do is actually invoke the code. The Cecil API contains many similarities to System.Reflection. For example:
var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(Path.Combine(projectDirectory, "bin", "Debug", "Something.dll"));
var controllerTypes = assembly.MainModule.Types.Where(t => t.BaseType?.FullName == "System.Web.Mvc.Controller")
.ToArray();
Another note is that .NET Framework (not .NET Core) contains the notion of AppDomains which can be loaded an unloaded. These act like .NET "sub-processes" within the one process and have rules about what can cross their boundaries. If you really need to both reload code and execute it, then this could be a solution.
Another option could be the Roslyn scripting API, which would work well if you want to dynamically load and execute source code (vs. compiled assemblies).
It looks like you're overlooking one small step: building your code. Once you rename the class to QuickSortAlgorithmmmm, you need to save and build that assembly.
Doing so will recreate the assembly (assuming your application doesn't have an open handle on it). After that, clicking the refresh button should show the new name.
If you can't reload the assembly because it has your GUI code in it too (which is running), you may want to separate out the classes that implement the interface into their own assembly, potentially build that separately, and copy it over into a directory where your app can find it (eg. in a Plugins directory).
I'm trying to understand reflection in more detail. The project I'm working on is intended to be an internal package, consumed by multiple developers. The problem, we parse a lot of data from varying departments. With documents that have varying headers, ordering, and often abbreviations of the name within the header.
Example: (Delimited Example)
Department A :
Date, Volume, Depth, Turbidity
Date and Time, Volume, Turbidity, Depth
Date, Vol., Turb., Dep.
Date, NTU, Vol, Dep ft
Department B:
Date/Time, Flow, Level, Velocity
Timestamp, Lvl, Flow, Vel.
So in the library I wanted to include a mapping file, with a method that in essence would be called GetHeaderConfigurations. Whomever references this library would be able to call the library with a user friendly name, but would pass an object with certain information.
The important piece would be their object and a namespace. Which I would recurse the namespace for classes, ones that are details about the header within the file.
The problem:
public static IEnumerable<Type> GetHeaderConfiguration(FileConfiguration configuration)
{
var assembly = Assembly.Load(configuration.HeadersNamespace);
// Some more code
}
When I call that from another application that references the library, I don't receive all of the classes. The application builds the object, then stores the namespace in the following manner "Sample.Headers.LabConfiguration". I execute the following:
var headers = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsClass && t.Namespace == "Sample.Headers");
The above does return all the classes within the directory in the solution, but for some odd reason when I attempt to load the assembly the code fails.
I believe the issue is when I call Assembly.Load I'm passing a namespace, not an assembly. Which leads me to the root of the question I'm hoping to understand. How can I successfully use that namespace? How can I load the internal properties?
Assembly.Load() does just that, loads a new assembly (roughly speaking, a DLL or EXE). If you just want to look for classes within the current assembly, use Assembly.GetExecutingAssembly() to get the currently executing Assembly object, and then call GetTypes() on that.
var assembly = Assembly.GetCurrentlyExecutingAssembly();
var headers = assembly.GetTypes().Where(...);
MSDN has the following note regarding performance:
For performance reasons, you should call this method only when you do not know at design time what assembly is currently executing. The recommended way to retrieve an Assembly object that represents the current assembly is to use the Type.Assembly property of a type found in the assembly, as the following example illustrates.
Unless you're running this code many times in a tight loop, there's no reason to be concerned with performance in my opinion. But if you want to follow MSDN's advice, you can replace Assembly.GetExecutingAssembly() with typeof(ThisClass).Assembly where ThisClass is the name of the class containing the code. But Assembly.GetExecutingAssembly() still works (and doesn't require coupling with the class name).
I am writing a customer class which will read CS files and spit out information based on method names and their various parameters.
This essentially reads each line looking for keys (public, class, etc) and then sees what its all about. Anyway this bit works fine, what I'm having issues with is dealing with various different Types.
So what I need to do is work out whether the type is one found natively in .Net, or something I've created, I'm really not bothered which way round just as long as I have some way of telling.
I've tried Type t = Type.GetType("My.Namespace.Classname"); but this just returns null even with the full namespace and name of my custom class object. However if I was to do the same code but with System.String it works perfectly fine, but I can't really account for each possible namespace in the entire framework. This will mean I need a way to get the type without the full namespace, or know how to check my own custom objects using GetType.
Can anybody provide any suggestions on how to go about this? Even if it was creating a new instance of the objects that would be enough, but again I don't have the full namespace for .Net objects.
Edit: Bit of a background
What I'm doing is reading classes that I've created in a StreamReader, reason being that I'm creating lots of them and need to do making between objects that one system will be able to understand, and another, so this code would read everything and just create the mapping for me. And in most cases this is perfectly fine, it is only when I have custom types, so I want to identify these are mark them.
I've tried Type t = Type.GetType("My.Namespace.Classname"); but this
just returns null
You need to provide the full assembly-qualified name:
Type t = Type.GetType("My.Namespace.Classname, MyAssembly");
From MSDN:
Parameters
typeName
Type: System.String
The assembly-qualified name of the type to get. See AssemblyQualifiedName. If the type is in the currently executing
assembly or in Mscorlib.dll, it is sufficient to supply the type name
qualified by its namespace.
Anyway, if you're looking to parse C# code an analyze it, I would take a look at NRefactory - an open source C# parser -.
Here's an introduction in CodeProject to NRefactory.
I've tried Type t = Type.GetType("My.Namespace.Classname"); but this just returns null even with the full namespace and name of my custom class object.
I suspect that's because it's not in the calling assembly or mscorlib, which are the only two assemblies checked by Type.GetType for names which aren't assembly-qualified.
If you know all the assemblies involved, you could run through each of them calling Assembly.GetType(namespaceQualifiedName) on each of them.
However, if you don't even have the namespace-qualified name, you should possibly create a lookup of all types in all the relevant assemblies, based on their names. For example:
var lookup = assemblies.SelectMany(a => a.GetTypes())
.ToLookup(t => t.Name);
At that point, for each name you have(e.g. Classname in your example) you can find all the types with that name:
foreach (var type in lookup[name])
{
// Do something with type
}
Type.GetType(some_type_name) will return type object if some_type_name is name of type declared any assemblies loaded at the moment, or in Mscorlib.dll
So if your are parsing your types from .cs files and not loading assebly - it will always be null with types names from your source file
I've got an object called "Communication" that has a method to "CreatePdfFromTemplate". This method is going to be called from a Windows Service that has a SqlDependancy on a table that will notify when a new row is added by a method on a website.
Into my method, I pass a list of custom objects that have an "Id" and a "Name". The name, is the name of the object I need to load using reflection. For example, "Instruction". The "Id" is the Id of the object referred to in "Name" that needs to be loaded from the database. This object is not referenced or available in the runtime of my "Communication" DLL.
I'm currently falling at the first hurdle. I am trying to do the following as a first step:
// Load object information using Reflection
Type objectType = Assembly.GetExecutingAssembly().GetType(queueObject.Name);
int objectId = queueObject.Id;
I have found some info from my searches for answers that say there is a way to load a DLL by making it available in the application cache or the GAC, but I wasn't sure if this was the best way to go.
I've never used Reflection before so if you have any advice on it, or any advice on the way I have chosen to structure this in general (i.e. website adds row to DB table, SqlDependancy in Windows Service fires, calls to Communication service DLL to create PDF).
Just to give you some more information, the reason I have chosen to do it like this, is because my templates contain tags such as {Instruction.CreatedDate} where "Instruction" is the name of the object and "CreatedDate" is the name of a property, the value of which will replace the tag.
Any help on how to load this "Instruction" object in my Reflection or just on my structure in general is much appreciated. Let me know if I haven't given enough info or if what I've said isn't clear enough (this is my first StackOverflow question, although I am a long time lurker).
Thanks.
--UPDATE--
Ok, using the idea put forward from Maarten, I have managed to load my assembly and get a type from it, but I've done it slightly differently. I wasn't able to put in a specific path using the Assembly.LoadFile method, so I've done it like this:
Assembly executingAssembly = Assembly.GetExecutingAssembly();
Assembly objectAssembly = Assembly.Load(executingAssembly
.GetReferencedAssemblies()
.Where(a => a.Name == "Common")
.FirstOrDefault());
This works because the Type I am trying to get, is part of a referenced assembly in my Communication service called "Common" (which is an installed package using nuget to help keep it up to date, as it changes quite often).
Any further posts on how I'm doing this and if it's the right or wrong way would be appreciated though!
Load the assembly using Assembly.LoadFile or another overload.
Get the type using Assembly.GetType.
Use the Activator.CreateInstance once you have the type.
Cast it to dynamic, and call your method, or set your property. I'm assuming you are using .net 4.0.
var myAssembly = Assembly.LoadFile(...);
var myType = myAssembly.GetType(...);
dynamic myObject = Activator.CreateInstance(myType);
if (myObject != null) {
var createdDate = myObject.CreatedDate;
}