Mono.Cecil - Wrong mscorlib version - c#

I am having issues trying to get Mono.Cecil to use the correct "mscorlib" version when using a TypeReference. I am adding a new variable to a Method and doing something along the following. However, it is adding a reference to the 4.0 mscorlib instead of the 2.0 mscorlib. I am having to run this application using the .NET Framework 4.5 so I am not able to use a lower version unless I re-write other people's code that I don't have access to.
TypeReference typeReference = CSharpModule.Import(Type.GetType("System.Nullable`1[[System.Boolean, mscorlib, Version=2.0.0.0]], mscorlib, Version=2.0.0.0"));
methodBody.Variables.Add(new VariableDefinition(typeReference));
I have tried to search around for an answer on how to get the correct version and I apparently have to use the Cecil Type System, but I am not able to find any examples of how to do this.

You should attempt to load the type by using TypeReference constructor,
https://github.com/lextm/obfuscar/blob/master/Obfuscar/Obfuscator.cs#L1204
My project Obfuscar shows an example of how to do so. You need to pay much attention to the library.MainModule.TypeSystem.Corlib part, so that the type is loaded from the proper mscorlib assembly.

So I was able to fix this by doing the following. Create a TypeReference using what is available to the MainModule.
assemblyDefinition.MainModule.GetType("System.Nullable`1[[System.Boolean]]", true)

Related

C# - Getting all assemblies through reflection and their types

What I am trying to achieve is get all assemblies from solution with reflection and then their types, so I can have them inside collection Type[] using .NET Core 2.0.
What I can use is
AppDomain.CurrentDomain.GetAssemblies(); - the problem is that this will get all referenced and used assemblies. In my case I want to get all assemblies that are referenced, but not necessary used. So the problem is that JIT compilation is removing references for projects that are not used, so in that case this wouldn't work.
Other option is to get location of DLLs using Assembly.GetExecutingAssembly().Location and then load all assemblies. The problem here is that, when latter I want to use .GetTypes() this throw exception from type System.Reflection.ReflectionTypeLoadException and then loader exception I have System.IO.FileNotFoundException: Could not load file or assembly Microsoft.EntityFrameworkCore. The issue, is that it's trying to use libraries, which cannot find, apperantly loading DLLs using Assembly.LoadFrom(dll) doesn't seem to load dependencies (libraries) as well.
What I found is BuildManager.GetReferencedAssemblies, from what I read so far, it's saying that this could work and it's getting all references, even if they're not used, so I also found it in MsBuild library, but doesn't contains that method, so I might be referencing wrong package.
I am open for any suggestions, how I can load all solution assemblies and their types from .NET Core 2.0 project.
Thanks in advance!
I had a very similar problem. I am not sure if this is the solution for your case but List<Assembly> usedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Select((item) => Assembly.Load(item)).ToList(); could be a solution.

How to enable forward compatibility on a reusable .NET library?

I'm in the process of creating a new minor release of a toy project of mine. This project is released on NuGet and is compatible with .NET 4.0 and up. Some of the new features I'm introducing require .NET 4.5 (users should be able to resolve IReadOnlyCollection<T> and IReadOnlyList<T>, both interfaces that were introduced in .NET 4.5), but I need to keep the project compatible with .NET 4.0, since not all developers can easily migrate to the latest .NET framework.
So the problem I’m facing is how to solve this ‘forward-compatibility’ problem. There are two solutions I’ve thought about, but both are not very attractive, so hopefully anybody can give me some ideas or guidance here.
Here are the two solutions I came up with:
Solution 1: Use #if compiler directives and build a DLL per .NET framework version and ship those versions using the NuGet packages and download at the project site.
Downside of this method is that when developers update their Visual Studio project from .NET 4.0 to .NET 4.5, they don't automatically get the .NET 4.5 version (with .NET 4.5 specific features). This violates the Principle of least astonishment and would leave developers dazed why the feature is not working, when they try using it a few months later.
Solution 2: Use one single DLL and emit type's on the fly that implement both new interfaces when they exist in the current app domain. This allows shipping a single DLL to the user and allows features to come available when the developer switches .NET framework versions in their project. This will make things 'just work'. This is the direction I’m currently heading btw.
Since I need to return a type that needs to implement the interfaces, the downside is that that type must be created at runtime using Reflection.Emit, ModuleBuilder, TypeBuilder, and the like. This is seriously nasty shizzle. But besides that, since this type must be created in a new (anonymous) assembly, I must make some internal types public (a type it needs to inherit from and an interface it needs to implement). Making those internal types public pollutes the API of the project and will disallow me from making changes to those types.
I believe these are my options, but I might be missing something obvious. So my question is, am I missing a possibility? Is there a way to circumvent the problems for solution 1 or would it be better to go with the hardcore root of runtime type emitting?
Have you thought about another custom assembly with the missing items in it? Then you test if a type/method exists (that would only exist in .net 4.5) and if it does, you load the assembly in.
That way you can keep the exact same methods and classes, and save yourself pain of doing all of that crazy emit (not to mention the perf hit you will take if you find yourself doing that much).
I have a project called Dynamitey that allows you to load a type at runtime and called it's static methods and constructors with the DLR. Which would be much less messy than a lot of reflection or emitting code to load an api that is not necessarily available.
dynamic bigIntType = new DynamicObjects.LateType("System.Numerics.BigInteger, System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
if (bigIntType.IsAvailable)
{
var one = bigIntType.#new(1);
var two = bigIntType.#new(2);
Assert.IsFalse(one.IsEven);
Assert.AreEqual(true, two.IsEven);
var tParsed = bigIntType.Parse("4");
Assert.AreEqual(true, tParsed.IsEven);
}
I also have a project called ImpromptuInterface, that will emit proxy types for interfaces around objects that duck callable match it (also uses DLR).
var targetType =Type.GetType("System.Collections.Generic.IReadOnlyList`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
var list = new List<string>{"lala", "la","lala"};
object readonlyList;
if(targetType != null){
readonlyList = Impromptu.DynamicActLike(list, targetType);
}

How do I add `System.Dynamic` to my project?

I am new to C# 4, especially the dynamic keyword. I have seen quite a number of tutorials and wish to try it out myself using VS 2012 Ultimate (MSDN).
Unfortunately I cannot seem to find System.Dynamic and cannot add a reference to it either. May I know where I can find the DLL for System.Dynamic and what I might have done wrong?
By default, VS 2012 already targets Fx 4.5, and System.Core is added as a reference.
The dynamic keyword is so common that when searching in Google yield a lot of un-related results.
Make sure you are targeting the .NET Framework version 4 or later.
Ensure your project references the System.Core assembly.
You will find the types and functionality of System.Dynamic in that assembly. Add the following line to your code files:
using System.Dynamic;
P.S.: In C#, in order for the dynamic keyword to work properly, you also need to reference the Microsoft.CSharp assembly. This assembly contains the late-binding functionality necessary for dynamic.
Whenever you want to search for documentation add msdn. Like msdn system.dynamic
You will find all the documentation you need.
System.Dynamic at MSDN
Namespace: System.Dynamic
Assembly: System.Core (in System.Core.dll)
The DLL is System.Core. Adding a reference to it will allow you to use the namespace System.Dynamic.

Indirectly accessing an assembly through reflection

OK, I have the following bit of code:
Assembly assembly = Assembly.LoadFile("W:\\AssemblyFoo.dll");
foreach (Type type in assembly.GetExportedTypes())
{
foreach (object attribute in type.GetCustomAttributes(false)) //Exceptio on that line
{
string attributeString = attribute.ToString();
}
}
The code throws the following exception: Could not load file or assembly 'AssemblyBar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
The problem is that one of the attribute is in AssemblyBar, which is referenced by AssemblyFoo, but not directly by the current's project (ProjectBaz) assembly. I'd rather avoid referencing AssemblyBar directly in ProjectBaz, since AssemblyFoo is selected by the user. What's the correct way to go about this ? I'm pretty sure I'm missing something easy.
I know it's possible since Reflector does it.
Mono's Cecil
You may circumvent the problem by not loading the assemblies through the built-in reflection
facilities, using a tool like Mono.Cecil instead. I've had good experiences in applying it for analysis tasks.
From the Cecil site:
with Cecil, you can load existing
managed assemblies, browse all the
contained types, modify them on the
fly and save back to the disk the
modified assembly.
CCI Metadata
As an alternative to Cecil, you might consider CCI Metadata by Microsoft Research. I have not used that tool, so I can not comment on how it stacks up to Cecil.
Hope this helps.
You could include AssemblyBar in you bin directory so that the clr can load it.
MemberInfo.GetCustomAttributesData() was introduced in .NET 4 so that you could examine custom attributes without having to instantiate them.
UPDATE: Taking closer look at MemberInfo.GetCustomAttributesData(), although it doesn't instantiate the attributes, it still need to load the assembly. My apologies.
Another possible route to investigate would be Mono Cecil. You can load the Mono.Cecil assembly and use it with the .NET Framework, not just Mono. It is much more powerful than System.Reflection and Reflection.Emit. According to its homepage:
Cecil does not need to load the assembly or have compatible assemblies to introspect the images.
This sounds exactly like what you're trying to do.

Reflection.Net: how to load dependencies?

I try to add an addons system to my Windows.Net application using Reflection; but it fails when there is addon with dependencie.
Addon class have to implement an interface 'IAddon' and to have an empty constructor.
Main program load the addon using Reflection:
Assembly assembly = Assembly.LoadFile(#"C:\Temp\TestAddon\Addon.dll");
Type t = assembly.GetType("Test.MyAddon");
ConstructorInfo ctor = t.GetConstructor(new Type[] { });
IAddon addon= (IAddon) ctor.Invoke(new object[] { });
addon.StartAddon();
It works great when addon do not use dependencie.
But if my addon reference and use an another DLL (C:\Temp\TestAddon\MyTools.dll) that is saved near the addon in disk, it fails:
System.IO.FileNotFoundException: Could not load file or assembly 'MyTools.dll' or one of its dependencies.
I do not wants to copy the addons DLL near my executable, how can i do to tell .Net runtime to search in "C:\Temp\TestAddon\" for any dependency?
Note that adding
Assembly assembly = Assembly.LoadFile(#"C:\Temp\TestAddon\MyTools.dll");
do not change anything.
If MyTools.dll is located in the same directory as Addon.dll, all you need to do is call Assembly.LoadFrom instead of Assembly.LoadFile to make your code work. Otherwise, handling the AppDomain.AssemblyResolve event is the way to go.
Have you looked into using an Inversion Of Control container? I use Castle Windsor with an external Boo file that lets me easily extend the applcation without having to recompile or worry about supplying dependencies
You can use reflection to access the private Assembly._GetReferencedAssemblies().
Although, the method could change in a future version of the .NET framework, it doesn't seem likely—ASP.NET heavily depends on it, though it's possible they could move it from mscorlib to System.Web which is the only assembly that I know of from where the method is referred to.
Assembly.LoadFrom works well until I try to use a webService in my addon, I had had a "Unable to cast object of type 'X' to type 'X'" exception.
It's ugly, but i will use Assembly.LoadFile with the AppDomain.AssemblyResolve.
Thanks guys.
Couple of options:
You can attach to AppDomain.AssemblyResolve to help the CLR resolve the assembly.
You could look into isolating add-ins into their own AppDomain (see System.AddIn namespace and this website).

Categories

Resources