我可以在同一程序集中将 C# 扩展方法的可见性限制为 类 吗?

Can I restrict the visibility of C# extension methods to classes in the same assembly?

假设我有这些文件:

MyCode.cs

namespace MyCodeNamespace
{
  public class MyClass
  {
    //OMITTED
  }

  internal static class MyExtensions
  {
    internal static void Foo(this string str)
    {
      //OMITTED
    }
  }
}

OtherCode.cs

using MyCodeNamespace;
namespace OtherCodeNamespace
{
  //OMITTED
}

这两个文件是同一个程序集的一部分。有什么方法可以让 MyCode.cs 可以访问 Foo 而 OtherCode.cs 不能访问 Foo?我的问题类似于这个问题: C# Extension Methods only visible and accessible within one class ("private") 但它接受的答案并不是我真正想要的。我想做一个只对我正在处理的代码可见的扩展方法,根据对上述问题的回答,有人仍然可以通过添加 "using" 语句来访问它。有没有一种方法可以创建一个扩展方法,该方法 对我的代码可见,并且 在其他地方 不可见,甚至对另一个 class 不可见] 在同一个程序集中?

我问是因为调用扩展方法的语法很方便,对我正在做的事情很有用(否则我只会创建一个私有方法),但我不想让别人看到它并在他们的代码中使用它,以防它没有按照他们假设的那样做。多亏了 Visual Studio 的智能感知,我的扩展方法目前显示在可用方法列表中(以及添加它们所在的命名空间的选项)。

.NET 平台中没有名称空间限制访问修饰符这样的东西。 From the docs

public : Access is not restricted.
protected : Access is limited to the containing class or types derived from the containing class.
Internal : Access is limited to the current assembly.
protected internal: Access is limited to the current assembly or types derived from the containing class.
private : Access is limited to the containing type.

这就是您需要处理的全部内容。所以答案是没有.

扩展方法只是语义糖,编译成与直接调用静态助手相同的 IL。

MyExtensionMethods.DoSomething(myObject);
myObject.DoSomething();

您不能限制它被调用,但您可以从 Intellisense 中删除它的可见性。

只需将您的扩展方法移动到不同的命名空间,在您的 MyCode.cs 中添加一个 using 语句并且不要在 OtherCode.cs

中包含该命名空间

[更新]

如果确实需要限制调用者,可以尝试使用反射来判断和限制,但这有点大材小用。最好简单地使用私有静态助手而不是这样做。

var frame = new System.Diagnostics.StackFrame(1, false);
var method = frame.GetMethod();
var type = method.DeclaringType;
// allow|deny type

我遇到了类似的问题。我不希望程序员在 ASP.NET Core 中配置服务时看到我的内部扩展方法。

我的解决方案是将所有扩展方法添加到 Startup.cs 中使用的命名空间 Microsoft.Extensions.DependencyInjection,用户可以看到这些方法。 (就像你一直做的那样。)

如果我想 "hide" 一些东西,我将扩展方法添加到 MyNamespace.Extensions。如果用户输入正确的名称,add using 的帮助程序将会显示,但默认情况下不会列出。

我知道这不是解决方案,但可能会对某人有所帮助。

想想类似的事情;

c# assembly, friend assembly 将尝试 InternalsVisibleTo; 如果您的 类 已关闭,可能不会有帮助,但您可以尝试一下;