Reputation: 18895
I'm seeing some unexpected behavior in my extension method resolution, and I'm attempting to figure out why. I've read Eric Lippert's Closer is Better article and I'm still confused.
First the call site:
// Assembly: DLaB.Xrm.2016.Tests
using DLaB.Xrm.Entities;
using DLaB.Xrm.Test;
using Microsoft.Xrm.Sdk;
namespace DLaB.Xrm.Tests
public class TrialClass{
{
public void Delete(){
IOrganziationService service = GetService();
Id<Contact> id = GetId();
service.Delete(id); // Call Site in Question
}
}
}
IOrganizationService Defines a delete method with this signature:
// Assembly: Microsoft.Xrm.Sdk
void Delete(string entityName, Guid id);
I have defined Extension method overloads on the IOrganziationService in two different namespaces, in two different assemblies:
//Assembly: DLaB.Xrm.2016
//Namespace DLaB.Xrm
public static void Delete(this IOrganizationService service, Entity entity) { ... }
public static void Delete(this IOrganizationService service, EntityReference entity) { ... }
//Assembly: DLaB.Xrm.Test.2016
//Namespace DLaB.Xrm.Test
public static void Delete(this IOrganizationService service, Id id) { ... }
public static void Delete<T>(this IOrganizationService service, Id<T> entity) where T : Entity { ... }
I have also defined implicit operators for the Id Class that convert it to an Entity
or an EntityReference
The Call Site
service.Delete(id)
shows a compiler error: Error CS0121 The call is ambiguous between the following methods or properties: 'Extensions.Delete(IOrganizationService, Entity)' and 'Extensions.Delete(IOrganizationService, EntityReference)'
Which I understand from my implicit operators I've defined. What I'm not understanding, is why the DLaB.Xrm
namespace is closer than the DLaB.Xrm.Test
namespace, even though I do not have a using directive for it.
Upvotes: 1
Views: 228
Reputation: 18895
There are 6 rules of closeness defined in Eric's Blog:
The first 3 do not apply since there is no applicable method for an interface. The 4th is the key. DLaB.Xrm is in a nested namespace, even though its in a different assembly. I had falsely believed that you had to list the using directive of the extension method in order to be able to access it from another class. I now know that extension methods in nested namespaces are automatically available.
Changing namespace DLaB.Xrm.Tests
to namespace NotNested.DLaB.Xrm.Tests
eliminates all the rules of closeness, and the ambiguous call is resolved by normal signature overload resolutions rules. The actual fix I used was just to make the Delete call generic, which eliminates the two implicit conversion overloads from contention, and allows the call to be resolved to my preferred method.
Upvotes: 2