diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b84b5e24f..591362c6f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Fixed * Fixed a bug that would cause a `NullReferenceException` to be reported during compilation of a class containing a getter-only `RealmObject` property. (Issue [#2576](https://github.com/realm/realm-dotnet/issues/2576)) * Fixed an issue that would result in `Unable to load DLL 'realm-wrappers'` when deploying a WPF .NET Framework application with ClickOnce. This was due to the incorrect BuildAction type being applied to the native libraries that Realm depends on. (Issue [#1877](https://github.com/realm/realm-dotnet/issues/1877)) +* Fixed a bug that would sometimes result in assemblies not found at runtime in a very specific edge scenario. More details about such a scenario can be found in its [PR](https://github.com/realm/realm-dotnet/pull/2639)'s description. (Issue [#1568](https://github.com/realm/realm-dotnet/issues/1568)) ### Compatibility * Realm Studio: 11.0.0 or later. diff --git a/Realm/Realm.Weaver/Extensions/ModuleDefinitionExtensions.cs b/Realm/Realm.Weaver/Extensions/ModuleDefinitionExtensions.cs new file mode 100644 index 0000000000..bba4a144ce --- /dev/null +++ b/Realm/Realm.Weaver/Extensions/ModuleDefinitionExtensions.cs @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2021 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +using System.ComponentModel; +using System.Linq; +using Mono.Cecil; + +[EditorBrowsable(EditorBrowsableState.Never)] +internal static class ModuleDefinitionExtensions +{ + public static ModuleDefinition ResolveReference(this ModuleDefinition module, string assembly) + { + var assemblyNameReference = module.FindReference(assembly); + if (assemblyNameReference != null) + { + return module.AssemblyResolver.Resolve(assemblyNameReference).MainModule; + } + + return null; + } + + public static AssemblyNameReference FindReference(this ModuleDefinition module, string assembly) + { + return module.AssemblyReferences.SingleOrDefault(a => a.Name == assembly); + } +} diff --git a/Realm/Realm.Weaver/ImportedReferences.cs b/Realm/Realm.Weaver/ImportedReferences.cs index a4397bbd29..67b3b27c6b 100644 --- a/Realm/Realm.Weaver/ImportedReferences.cs +++ b/Realm/Realm.Weaver/ImportedReferences.cs @@ -207,7 +207,7 @@ protected ImportedReferences(ModuleDefinition module, TypeSystem types) }; // If the assembly has a reference to PropertyChanged.Fody, let's look up the DoNotNotifyAttribute for use later. - var PropertyChanged_Fody = Module.AssemblyReferences.SingleOrDefault(a => a.Name == "PropertyChanged"); + var PropertyChanged_Fody = Module.FindReference("PropertyChanged"); if (PropertyChanged_Fody != null) { InitializePropertyChanged_Fody(PropertyChanged_Fody); @@ -407,7 +407,19 @@ private void InitializePropertyChanged_Fody(AssemblyNameReference propertyChange protected AssemblyNameReference GetOrAddFrameworkReference(string assemblyName) { - var assembly = Module.AssemblyReferences.SingleOrDefault(a => a.Name == assemblyName); + var assembly = Module.FindReference(assemblyName); + + // Since Remotion.Linq has all the needed dlls references, try to find the right version there first + if (assembly == null) + { + assembly = Module.ResolveReference("Realm")?.ResolveReference("Remotion.Linq")?.FindReference(assemblyName); + if (assembly != null) + { + Module.AssemblyReferences.Add(assembly); + } + } + + // if Remotion.Linq failed to be loaded then we fall back to search versions in System.CoreLib if (assembly == null) { var corlib = (AssemblyNameReference)Module.TypeSystem.CoreLibrary; @@ -573,7 +585,7 @@ public static ImportedReferences Create(ModuleDefinition module, string framewor references.InitializeFrameworkMethods(); // Weaver may be run on an assembly which is not **yet** using Realm, if someone just adds nuget and builds. - var realmAssembly = module.AssemblyReferences.SingleOrDefault(r => r.Name == "Realm"); + var realmAssembly = module.FindReference("Realm"); if (realmAssembly != null) { references.InitializeRealm(realmAssembly);