You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

除Friend Assemblies外,还有哪些避免程序集泄漏的方法?

限制.NET程序集public成员仅被指定项目调用的替代方案

除了Friend Assemblies,以下几种方法可以有效防止程序集泄漏,限制特定程序集的访问权限:

1. 内部可见性+项目依赖管控

将基础设施项目中的实现类标记为internal,仅对外暴露必要的抽象接口(放在独立的应用层或契约项目中)。同时在解决方案层面严格管控项目引用:只允许Web项目直接引用基础设施项目,其他项目仅引用契约层的接口项目,无法直接访问基础设施的内部实现。

这种方式依赖编译时的项目依赖检查,一旦其他项目尝试引用基础设施项目,IDE会直接报错,适合结构清晰的分层架构(如Clean Architecture)。

2. 自定义Roslyn代码分析器

通过编写Roslyn分析器,在编译阶段检测非法引用行为:

  • 分析器扫描所有项目的代码,检查是否有非允许的项目引用了基础设施项目的public类型
  • 一旦检测到违规引用,直接抛出编译警告或错误,从源头阻止程序集泄漏

示例核心逻辑:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);
}

private void AnalyzeSymbol(SymbolAnalysisContext context)
{
    var typeSymbol = (INamedTypeSymbol)context.Symbol;
    if (typeSymbol.ContainingAssembly.Name == "InfrastructureProject")
    {
        var referencingAssembly = context.Compilation.Assembly;
        if (referencingAssembly.Name != "WebProject")
        {
            context.ReportDiagnostic(Diagnostic.Create(
                Rule, 
                typeSymbol.Locations[0], 
                $"禁止{referencingAssembly.Name}引用基础设施项目的类型"));
        }
    }
}

将这个分析器打包为NuGet包,添加到解决方案的所有项目中,即可实现编译时强制管控。

3. 依赖注入封装+接口隔离

在应用层定义抽象接口,基础设施项目以internal实现这些接口,同时提供一个仅允许Web项目调用的DI扩展方法:

// 应用层契约
public interface IOrderRepository { /* ... */ }

// 基础设施层实现(internal)
internal class EfCoreOrderRepository : IOrderRepository { /* ... */ }

// 基础设施层的DI扩展(public)
public static class InfrastructureServiceCollectionExtensions
{
    public static IServiceCollection AddInfrastructure(this IServiceCollection services)
    {
        services.AddScoped<IOrderRepository, EfCoreOrderRepository>();
        return services;
    }
}

其他项目只能依赖应用层的IOrderRepository接口,无法直接访问EfCoreOrderRepository,而Web项目通过调用AddInfrastructure方法完成服务注册,间接使用基础设施实现。

4. 运行时调用方验证

在基础设施的public类型中添加运行时检查,验证调用方程序集是否为允许的Web项目:

public class PaymentService
{
    public PaymentService()
    {
        var callingAssembly = Assembly.GetCallingAssembly();
        var allowedAssemblyName = "WebProject";
        var allowedPublicKeyToken = new byte[] { /* Web项目的公钥Token */ };
        
        if (callingAssembly.GetName().Name != allowedAssemblyName ||
            !callingAssembly.GetName().GetPublicKeyToken().SequenceEqual(allowedPublicKeyToken))
        {
            throw new InvalidOperationException("仅允许Web项目调用此服务");
        }
    }
}

这种方式属于运行时防护,虽然无法阻止编译引用,但能在非法调用时直接抛出异常,适合需要动态验证的场景(如插件化架构)。

5. 强命名程序集+权限控制

给基础设施和Web项目添加强命名,然后通过.NET的权限系统限制访问:

  • 为基础设施程序集设置自定义权限集,仅允许持有特定强命名密钥的Web程序集访问
  • 在基础设施代码中通过PermissionSet进行权限检查,拒绝未授权的调用方

这种方式配置较为复杂,适合对安全性要求极高的场景,通常结合代码访问安全(CAS)机制使用。


内容的提问来源于stack exchange,提问作者René

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:57:41