After two days of debugging this is what I did.
Drawing from experience I used Cecil to rewrite the assembly, cancelling out methods by just replacing all method bodies with simply throw new NotImplementedException
ignoring all constructors (initialization is a bit tricky and just can't just kill the method body of a constructor). After doing this the assembly was installed successfully. I didn't know what was the problem but I knew it had something to do with code. This was my assumption all along.
To find the actual method, I used a binary search. I replaced half of the methods in the assembly and if the error was not there I went left, otherwise right as long as I had a problem until I found the smallest set of methods that were responsible for the error. Given that it was more than 2000 methods and I took about 1-2 seconds to test each configuration, it saved a lot of time.
I managed to zero down on a single method rather easily and here it is (from what I could tell of my findings, this had to be in a generic class as well).
class Hashtable<K, V>
{
IEnumerable<KeyValuePair<K, V>> GetEnumerator()
{
var hashtable = new Hashtable();
return hashtable
.Cast<DictionaryEntry>()
.Select(x => new KeyValuePair<K, V>((K)x.Key, (V)x.Value))
.GetEnumerator();
}
}
Nothing in this code really results in any IL that's invalid, even though there's plenty of transformations applied by the compiler. If you put this in a database CLR assembly it will reject the assembly with an access denied
error with without any further information.
Eventually, I'm gonna file this as a bug with Microsoft, the error message should not be access denied
and furthermore this code is actually allowed because it doesn't do anything which isn't allowed under the safe permission set.