Thursday, January 03, 2008

Referencing different versions of an assembly - Part 2 (ILMerge)

This is where we stopped in Part 1:

image28

We have ended up with two merged assemblies (MergedA & MergedB) which are referenced by App1.

Now let's complicate things a little:

image

All I wanted to do is to use infra.dll (the version isn't critical for this discussion) inside my main application (App1).

 

If you try to use any type from infra.dll in App1 code and build the solution, you'll get:

The type "infra.xyz" exists in both 'MergedA.dll' and 'MergeB.dll'

 

What is it all about?

When I used infra.xyz type, the compiler tries to find where is it declared, but find at least two places (actually there are three). So it can't decide which one you want...

I got a question about this in a comment on Part 1 from Kevin Berridge, and actually I have crashed into the same problem few hours before, too.

 

The solution - ILMerge with /internalize switch:

The problem was created because all types inside infra.dll were exposed both by MergedA & by MergedB.

If we can make the infra part in the merged assembly internal only, our main application wouldn't be able to see it.

And this is exactly what /internalize does.
image
Only the first dll file in the merge list is left public (in yellow), and all the rest assemblies are converted to be internal (in turquoise).

You can see it using .Net Reflector:

clip_image001

Originally, Class1 was public (inside Infra)

clip_image001[6]

After merging with /internalize it is now Internal (inside MergedA)

clip_image001[4]

 

Now App1 knows of only one infra.xyz, and the build succeed!

 

Question for the next part:

What will happen if you merge App1 too?

 

Next: Part 3

1 comment:

Kevin Berridge said...

Thanks so much for this post!

I've summarized what I found in my own research and what I decided on in a post Two Versions of the Same Shared Assembly.