SharpCrafters Forum – PostSharp loads wrong assembly on silverlight weaving

SharpCrafters Support Forum

        


PostSharp loads wrong assembly on silverlight... Expand / Collapse
Author
Message
Posted 1/4/2010 1:58:00 PM


Community Member
Hi.
First I describe the problem. I have a silverlight assembly, which I instrument using PostSharp.Core (not Laos) attributes. However, the build fails with this exception:
PostSharp.CodeModel.BindingException occurred
 Message="Cannot find a method named 'GetEnumerator' with signature '() : [mscorlib]System.Collections.Generic.IEnumerator`1<!0>' in scope 'Wintellect.PowerCollections.CollectionBase`1'  (module = 'PowerCollections.dll')."
 Source="PostSharp.Core"
 StackTrace:
      at PostSharp.CodeModel.Collections.MethodDefDeclarationCollection.GetMethod(String name, IMethodSignature signature, BindingOptions bindingOptions) in C:\Dev\3rd_party\PostSharp\Core\PostSharp.Core\CodeModel\MethodDefDeclaration.cs:line 1503
 InnerException:


After wasting several hours investigating the issue, here are my findings.
- Our silverlight assembly along with all its dependencies lies in $(DEV)\windows\bin\Silverlight\Debug folder. This folder also includes the silverlight build of PostSharp.Public.dll and our aspects dll (silverlight build, of course). One of the dependencies is a silverlight build of PowerCollections.dll. These dependencies are 3rd party dlls, which were copied to the target folder from the $(DEV)\3rd_party\bin\Silverlight\Debug folder, which contains the silverlight builds of the relevant 3rd party libraries.
- PostSharp-1.5.targets along with all the required PostSharp assemblies lie in $(DEV)\3rd_party\bin\DotNet\Debug folder. This same folder also contains a .NET build of PowerCollections.dll, which only makes sense, because this folder contains all the .NET builds of our 3rd party libraries, where PostSharp and PowerCollections are examples of such.
- When PostSharp creates a map of used types, it loads PowerCollections.dll from the $(DEV)\3rd_party\bin\DotNet\Debug folder, despite the fact that the target is a silverlight build and there is the correct version of PowerCollections.dll in the target folder!!! If I delete this file, then PostSharp loads the correct version from the target folder - $(DEV)\windows\bin\Silverlight\Debug.

It looks like when loading dependencies, PostSharp prefers its home folder over the target folder and if there are different builds of the same library in both places, it loads the one from the home folder. This wrecks havoc in our scenario.

A very important note - different platform builds of the same library have identical assembly name - the same version, public key token, etc... So, technically, PostSharp may decide that the two versions are equivalent, although it can deduce pretty fast that one is a .NET build and another is a Silverlight build.

Now, one may say "what the hack, make the two builds differ in version and/or public key, like mscorlib does - .NET is 2.0.0.0 and Silverlight is 2.0.5.0, so that the different platform builds have different versions".

Sounds like the right thing to do, but this may not be as trivial as it seems. So, I would like to know whether it is possible to change PostSharp, so that it starts looking for referenced assemblies in the instrumentation target folder, rather than in its own home folder.

Thanks.
Post #668
Posted 1/4/2010 4:13:19 PM


Gael Fraiteur

SharpCrafters
It's not possible to change the order of directories in the search path, but something you may try (since I see you compile PostSharp yourself) is to edit the file AssemblyLocator.cs. You'll see:


           // 3. Look in directories containing the assemblies that are loaded in the AppDomain
           foreach ( string directory in priorityDirectories )
           {
               string location = ProbeDirectory( directory, requestedAssemblyName, "this directory contains an assembly that has already been loaded" );
               if (location != null)
                   return location;
           }
           
           // 4. Look in the list of files
           foreach ( string file in this.files )
           {
               string location = ProbeFile(file, requestedAssemblyName, "this file was explicitely added to the search path");
               if (location != null)
                   return location;
           }


Basically, invert points 3 and 4. The list of files is actually the list of references received by the C# compiler, so logically they should be processed by higher priority.

Unfortunately, I cannot make the change in PostSharp 1.5 since it may break something for some customers. I will consider doing the change in PostSharp 2.0 since it's still beta.

-gael
Post #669
Posted 1/4/2010 4:15:45 PM


Gael Fraiteur

SharpCrafters
<!-- m --><a class="postlink" href="http://www.postsharp.org/tracker/view.php?id=463">http://www.postsharp.org/tracker/view.php?id=463</a><!-- m -->
Post #670
Posted 1/4/2010 7:09:58 PM


Community Member
Hi Gael.

Why do you examine AppDomain.CurrentDomain.GetAssemblies() when trying to match the given assembly reference? After all, these are always .NET assemblies, because msbuild runs on the full .NET platform. However, the instrumented assembly may be Silverlight, Mono, Compact Framework, God knows what...

As I see it, this is a bug and its severity is not minor, but I may be wrong in reading this picture. Can you share the rationale, please?

Thanks.
Post #671
Posted 1/4/2010 7:21:13 PM


Community Member
Hi Gael.
Another question.
Observe the following piece of code from the AssemblyLocator.FindAssembly method:

// 2. Look in GAC
string gacLocation = Platform.Current.FindAssemblyInCache( assemblyName );
if ( gacLocation != null )
{
   return gacLocation;
}


My instrumented assembly is built using Silverlight platform, but Platform.Current returns
{PostSharp.PlatformAbstraction.DotNet.DotNet20Platform}


Of course, after all this is indeed the current platform. But the platform to search in GAC should be the Silverlight platform, not the current one. Again, I miss the rationale here and think this is a bug.
Post #672
Posted 1/4/2010 7:29:29 PM


Gael Fraiteur

SharpCrafters
Exact; there should not be a GAC lookup in that case.
Post #673
Posted 1/4/2010 7:35:36 PM


Gael Fraiteur

SharpCrafters
<!-- m --><a class="postlink" href="http://www.postsharp.org/tracker/view.php?id=465">http://www.postsharp.org/tracker/view.php?id=465</a><!-- m -->
Post #674
Posted 1/4/2010 7:50:45 PM


Community Member
Observing the code of the GetAssemblyNameForFrameworkVariant method I deduce that PostSharp.Public and PostSharp.Laos must have identical public keys on all the platforms. In fact the rules are rather strict - the full names of the respective assemblies of the different platform builds must differ only in their short name, where the platform code is appended to the short name, So that PostSharp.Public becomes PostSharp.Public.SL.dll on Silverlight, having exactly the same public key as PostSharp.Public.dll for the full framework.

Am I right?

Thanks.
Post #675
Posted 1/4/2010 7:53:53 PM


Community Member
BTW, how should I fix the FindAssemblies method in the meantime? I need it to work correctly both for the full .NET platform and Silverlight. Right now I have just commented out the regions 0, 2 and 3.

Thanks.
Post #676
Posted 1/5/2010 7:17:54 AM


Gael Fraiteur

SharpCrafters
That PostSharp.Public becomes PostSharp.Public.SL.dll on Silverlight, having exactly the same public key as PostSharp.Public.dll for the full framework.

Am I right?


Yes, it's kind of a hack, but it's how it works currently (this is actually just a utility method allowing to map a System.Type to an ITypeSignature).
Post #677
Posted 1/5/2010 7:21:16 AM


Gael Fraiteur

SharpCrafters
BTW, how should I fix the FindAssemblies method in the meantime? I need it to work correctly both for the full .NET platform and Silverlight. Right now I have just commented out the regions 0, 2 and 3.


0 and 2 should only be skipped if this.Domain.ReflectionDisabled == true. 3 and 4 should be swapped.
Post #678
Posted 1/5/2010 8:35:42 AM


Community Member
Thanks, Gael.
I will do so.
Post #679
« Prev Topic | Next Topic »


All times are GMT +1:00, Time now is 11:42am

Powered By InstantForum.NET v4.1.4 © 2010
Execution: 0.163. 7 queries. Compression Disabled.