views:

1540

answers:

7

Is there a way to modify existing .NET assemblies without resorting to 3rd party tools? I know that PostSharp makes this possible but I find it incredibly wasteful that the developler of PostSharp basically had to rewrite the functionality of the whole System.Reflection namespace in order to make existing assemblies modifiable.

System.Reflection.Emit only allows the creation of new, dynamic assemblies. However, all the builder classes used here inherit from the basic reflection classes (e.g. TypeBuilder inherits from System.Type). Unfortunately, there doesn't seem to be a way to coerce an existing, dynamically loaded type into a type builder. At least, there's no official, supported way.

So what about unsupported? Does anyone know of backdoors that allow to load existing assemblies or types into such builder classes?

Mind, I am not searching for ways to modify the current assembly (this may even be an unreasonable request) but just to modify existing assemblies loaded from disc. I fear there's no such thing but I'd like to ask anyway.

In the worst case, one would have to resort to ildasm.exe to disassemble the code and then to ilasm.exe for reassembly but there's no toolchain (read: IL reader) contained in .NET to work with IL data (or is there?).

/EDIT:

I've got no specific use case. I'm just interested in a general-purpose solution because patching existing assemblies is a quite common task. Take obfuscators for example, or profilers, or AOP libraries (yes, the latter can be implemented differently). As I've said, it seems incredibly wasteful to be forced to rewrite large parts of the already existing infrastructure in System.Reflection.

+4  A: 

It would help if you could provide a more specific use case, there are probably better ways to fix your problem than this.

In .NET 3.5 it's possible to add extension methods to existing framework classes, perhaps that is enough?

Wedge
A: 

You could load the assembly using IronRuby, and mixin all the functionality you can dream of

Xian
+4  A: 

You can use MethodInfo.GetMethodBody().GetILAsByteArray(), modify that, and then plug it back into MethodBuilder.CreateMethodBody().

Mark Cidade
Do you have an example please ? I cannot find any that let me create a method builder on an existing assembly or type, only ones that create new ones.
Preet Sangha
This is only for creating new ones. You might be able to load an assembly from disk in a separate AppDomain, though, and then unload the AppDomain and save the new assembly over the old one.
Mark Cidade
+2  A: 

One important point: if the assembly is signed, any changes will fail and you'll end up with a dud.

Joel Coehoorn
A: 

.NET Framework assemblies are signed and just as Joel Coehoorn said you'll get a dud.

Andrei Rinea
A: 

@Wedge:

You're right. However, there's no specific use case here. I've modified the original question to reflect this. My interest was sparked by another question where the asker wanted to know how he could inject the instructions pop and ret at the end of every method in order to keep Lutz Roeder's Reflector from reengineering the (VB or C#) source code.

Now, this scenario can be realized with a number of tools, e.g. PostSharp mentioned above and the Reflexil plugin for Reflector, that, in turn, uses the Cecil library.

All in all, I'm just not satisfied with the .NET framework.

@Joel:

Yes, I'm aware of this limitation. Thanks anyway for pointing it out, since it's important.

@marxidad:

This seems like the only feasible approach. However, this would mean that you'd still have to recreate the complete assembly using the builder classes, right? I.e. you'd have to walk over the whole assembly manually.

Hmm, I'll look into that.

Konrad Rudolph
You can also try LinFu.AOP--it lets you do everything Postsharp does, albeit at runtime: http://www.codeproject.com/KB/cs/LinFuPart6.aspx
plaureano
After a quick glance, it looks to me that LinFu does not do everything at runtime. From the docs: "The first thing that we need to do is use LinFu.AOP to modify SampleLibrary.dll so that all of the Person class’ methods can be dynamically intercepted (or replaced) at runtime. In general, LinFu.AOP gives you two options for modifying your assembly for interception. You can either use it as a custom MSBuild task as part of your projects or you can use PostWeaver.exe to manually modify it using the command line."
Todd Stout
+6  A: 

Mono.Cecil also allows you to remove the strong name from a given assembly and save it back as an unsigned assembly. Once you remove the strong name from the assembly, you can just modify the IL of your target method and use the assembly as you would any other assembly. Here's the link for removing the strong name with Cecil:

http://groups.google.com/group/mono-cecil/browse_thread/thread/3cc4ac0038c99380/b8ee62b03b56715d?lnk=gst&q=strong+named#b8ee62b03b56715d

Once you've removed the strong name, you can pretty much do whatever you want with the assembly. Enjoy!

plaureano