Load Assembly of a Project - c#

Hi I do not know if this is possible or not but I have a c# Project lets say A and I am trying to access Assembly Info of another project B so that i can get Method Info of project B using Reflection. Problem is that i can not think of a way to integrate those two. Project A provides a openFileDialogue and it selects .csproj file. Reads it and extracts what files are being used in project B.
Can you suggest me a work out?

I don't think you can do that by using reflection. To work with reflection you'll need an assembly, not csproj (or cs files). You should look for a parser, maybe use the Roslyn APIs, that will give you information about the source code in syntax tree format.
http://blogs.msdn.com/b/visualstudio/archive/2011/10/19/introducing-the-microsoft-roslyn-ctp.aspx

Each .csproj file is XML, so you can read that in pretty easily. Listed in that file is every file included in the project, so you can parse the XML .csproj file to find all the .cs files.
From there, if you need to extract MethodInfo, you would have to either parse the .cs files, or use something like Roslyn to parse the code into its syntax tree, and find the methods that way.
Can you just use the built assembly (.exe or .dll) from "Project B" instead of its .csproj file? It would be a lot easier to load the assembly's reflection info, and just loop over every class and evey method...

Use Assembly.LoadFile to load directly the compiled assembly - i.e. the DLL or EXE; this will give you an Assembly object on which you can call GetTypes() etc. to access all the info you want.

Related

Can we modify the existing assembly(dll) by using CSharpCompilation.Create()? If not how to do?

I am using CSharpCompilation.Create to create assembly from scratch. The thing I got to know is this always creates a new assembly. Is there anyway to add/modify the existing DLL in Roslyn? This is because I am building a tool where a user can type C# code in richtextbox and compile it to add it to the existing assembly. Is it possible, if not what I am doing wrong and what is the right way?
P.S.,
I have also tried CSharpCodeProvider as well to compile the code, but it is also Generating assembly with only the code I typed in richtextbox. The output assembly did not have other classes in that.
Yes as mentioned in comment by Klauss Gutter, you have to build the assembly individually and merge it later using ILMerge. I know ILMerge is out of support and is deprecated. You can use ILRepack to do this. It provides the same functionality as ILMerge.
You can use NuGet Package to install ILRepack first and then add reference to the ILRepack.exe to your project to use its methods to pack multiple assemblies in to one.
Roslyn or CSharpProvider wont help you to merge your assemblies. The main motto of these are to compile and create an assembly not merge.

Add class into current assembly

I have a current assembly in my application and I would like to add a class from external cs file into this assembly. Is it possible to do it? I would like to use it like plug-ins. Now I'm trying use:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
and Activator,but without success. My application is using Roslyn, so maybe it can do it.
Any idea will be appreciated.
Edit: Next problem with it is: Can I use external file (cs file with class) to get instance from this file but the constructor of class needs reference to sceneManager from current assembley. So is possible to send a reference to Roslyn of something like that and get instance of class from it?
You cannot modify an existing assembly that has already been loaded.
Instead, you can compile code to a new assembly (using Roslyn, CodeDOM, Sigil, or similar libraries) and load that assembly using reflection.
A '.cs' file by itself is just text. You can't do anything with it without compiling it through some route. But no: you can't add extra classes into an assembly at runtime. You can compile the code at runtime via CSharpCodeProvider or similar, and load the generated assembly. It is a lot of messing, though. Depending on the context, tools like Iron Python may be preferable, if you need to do a lot of things from scripts at runtime.

C# using others code

Iv'e downloaded a C# interval tree collection class class from here http://intervaltree.codeplex.com/SourceControl/list/changesets -> Right hand side -> Download.
However I can't open the whole project on my Microsoft Visual C# 2010 Express (that also runs C# XNA) because
Solution folders are not supported in this version of the application
Also I just want the class to use separately in my own seprate project.
I tried to copy the three important seeming files Interval.cs, IntervalNode.cs and IntervalTree.cs into my project but this generated the compile error
There are no importers which handle this file type
I've also tried to copy and paste the contents of the three files into my project, encapsulating them into there own namespace as well as there was a lot of code. I had to rearange some of the usings a little but have run into the problem that possibly it wants PowerCollections .dll and .pcb files as using Wintellect.PowerCollections; causes
The type or namespace name 'Wintellect' could not be found (are you missing a using directive or an assembly reference?)
I'm not sure how to continue or if I'm doing the right thing at all in how to get this class to work.
Add the library to your solution
Copy the IntervalTreeLib directory into your solution directory. Then, right-click your solution, and add existing project. Point it at IntervalTreeLib.csproj in IntervalTreeLib, and click Open. That should add the IntervalTreeLib project to your solution.
Add a reference to the library in your project
Then, in your project, add a reference to the IntervalTreeLib proejct:
- Right click the References folder, and Add Reference. Click the Projects tab, and select IntervalTreeLib.
Use the classes in your code
To use classes from the library in your source then, you need to either add:
using IntervalTreeLib;
void Foo() {
IntervalTree<int, int> tree = new ...
}
Or, refer to them by their full name:
IntervalTreeLib.IntervalTree<int, int> tree = new ...
Open the IntervalTreeLib.csproj file if you want to be able to open the project in it's entirety (or in your current solution add an existing project (you can right-click on the solution) and select the IntervalTreeLib.csproj). If you are trying to grab just the code file in your project, ensure you also grab the PowerCollections.dll file (I see it is in the same folder as the code files) or your code will not compile (as you have discovered). You'll need to add a reference to it and include the needed using statement at the top of the code files making use of this library (or use fully qualified name with the namespace).
using IntervalTreeLib;
or
var myObj = new IntervalTreeLib.[WhateverClass](...);
Also, make sure you read the license.txt file. You may need to include it if you are using the code. Give credit where it is due.
UPDATE:
If the test project is causing you problems, just open the library project. Ideally you could just open that and compile it, adding the output DLL files that are generated directly into your solution. This is ideal unless you are planning on changing the library source code itself.
Add the library to the references of the project you want to use it.
Since discussing that you are able to build Intervallib.dll, we will discuss about how you should the dll in your project.
Now in your proj, right click on the references part and add the dll intervallib.dll to your references. In your game.cs file, have the reference to the namespace as -- using IntervalTreeLib;
then you should actually copy the dll powercollections.dll to the bin directory of proj directory also.
you should copy this dll because there is an indirect link to the dll as it is used in IntervalTreeLib.dll
following these steps, I was able to execute this project.

Creating extra type definitions at compile time

Recently I've been working with MSTest, and I noticed that the testframework generates accessor classes dynamically at compile time. How can one do this?
There's an xml file in a VS2010 C# project. I'd like to make an enum out of certain data in this xml file. Can this be done? And if so, how?
I'd recommend T4 templates myself. Very easy to use and specifically designed to allow you to generate code during the build. http://msdn.microsoft.com/en-us/library/bb126445.aspx
Method A) Read the xml file, parse it, generate C# code from it, write out the C# code to a temp file, compile that code; delete the temp file.
Method B) Read the xml file, parse it. Generate IL code directly from it using method in the System.Reflection.Emit namespace, or those in the System.CodeDom namespace.
MSTest achieves this in a couple of different ways. In short they essentially do the following IIRC
Hook into the build system
At the start of the build they generate their acessor's into hidden files in the project
After the build completes they remove their files
You can achieve a similar effect via the same process. However hooking into the build system is a bit complicated. A much simpler approach is to build a custom tool / code generator and hook. This allows you to process a file at build time and spit out a corresponding code file to include in the build.
There are several examples on the web on how to achieve this. Here are a couple
http://www.raboof.com/Projects/VsCodeGeneratorShim/
http://www.ramymostafa.com/?p=204
The System.CodeDom Namespace is one option you have.
It allows you to automatically generate a class using C# Code and compile it as well.
You can maybe call this code as a postbuild during your build of your project.
This example shows how to create a class using this namespace

c# best way to grab a xsd from a referenced project

My application references another a project which has an XSD file in it.
Whats the best way to get that XSD?
I did a bit of googling and found suggestions like load the assembly and get it from that, is there no easier way?
If the XSD is an embedded resource in the assembly, then you need to get it from the assembly.
If your project references and uses the assembly, then you won't need to load it again (you don't need 2 copies in memory).
The easiest way to get to the assembly, would be from one of the types defined in it:
Type t = typeof(TypeInOtherAssembly);
Assembly assembly = t.Assembly;
assembly.GetManifestResourceStream(...);
If you've added the XSD as a resource then the easiest way is to make the auto-generated Properties.Resources class publicly visible and reference the auto-generated property. You could also keep Properties.Resources internal and add an InternalsVisibleTo attribute to allow your other assembly to have access.
Other than that approach, you can use the GetManifestResourceStream on the target assembly to extract the XSD information.

Categories