Pure.DI高级配置自定义属性与元数据注入终极指南【免费下载链接】Pure.DIPure DI for .NET项目地址: https://gitcode.com/gh_mirrors/pu/Pure.DIPure.DI作为.NET平台的编译时依赖注入框架提供了强大的自定义属性与元数据注入功能让开发者能够完全掌控依赖注入的细节配置。本文将深入探讨如何利用自定义属性实现更灵活、更精确的依赖注入配置提升代码的可维护性和可扩展性。为什么需要自定义属性在复杂的应用场景中标准的依赖注入配置可能无法满足所有需求。Pure.DI的自定义属性功能允许开发者统一元数据管理将标签、顺序和类型信息整合到单个属性中领域特定语义创建符合业务逻辑的专用属性减少重复代码避免在多个地方重复配置相同的元数据增强可读性使注入配置更贴近业务语义自定义属性的基础配置独立属性配置Pure.DI支持三种类型的自定义属性配置每种属性都可以单独注册DI.Setup(nameof(PersonComposition)) .TagAttributeMyTagAttribute() // 注册标签属性 .OrdinalAttributeMyOrdinalAttribute() // 注册顺序属性 .TypeAttributeMyTypeAttribute() // 注册类型属性 .TypeAttributeMyGenericTypeAttributeTT() // 注册泛型类型属性属性定义示例// 顺序属性 - 控制注入顺序 [AttributeUsage( AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field)] class MyOrdinalAttribute(int ordinal) : Attribute; // 标签属性 - 标识特定依赖 [AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] class MyTagAttribute(object tag) : Attribute; // 类型属性 - 指定具体类型 [AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] class MyTypeAttribute(Type type) : Attribute; // 泛型类型属性 [AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] class MyGenericTypeAttributeT : Attribute;通用属性一站式解决方案为了简化配置Pure.DI支持创建通用属性将标签、顺序和类型信息整合到一个属性中通用属性定义[AttributeUsage( AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] class InjectAttributeT(object? tag null, int ordinal 0) : Attribute;配置通用属性DI.Setup(nameof(PersonComposition)) .TagAttributeInjectAttributeTT() // 从第一个参数读取标签 .OrdinalAttributeInjectAttributeTT(1) // 从第二个参数读取顺序 .TypeAttributeInjectAttributeTT() // 从泛型参数读取类型使用通用属性class Person([Injectstring(NikName)] string name) : IPerson { private object? _state; [Injectint(ordinal: 1)] internal object Id ; public void Initialize([InjectUri] object state) _state state; public override string ToString() ${Id} {name} {_state}; }实际应用场景场景1数据库连接配置假设我们需要为不同的数据库连接配置不同的标签[AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Property)] class DatabaseAttribute(string connectionName) : Attribute; DI.Setup(nameof(AppComposition)) .TagAttributeDatabaseAttribute() .Bind(Primary).ToSqlConnection() .Bind(Backup).ToPostgresConnection() .RootIAppService(AppService); class AppService( [Database(Primary)] IDbConnection primary, [Database(Backup)] IDbConnection backup) { // 使用不同的数据库连接 }场景2日志级别配置[AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Property)] class LogLevelAttribute(LogLevel level) : Attribute; DI.Setup(nameof(LoggingComposition)) .TagAttributeLogLevelAttribute() .Bind(LogLevel.Info).ToInfoLogger() .Bind(LogLevel.Error).ToErrorLogger() .RootILoggingService(LoggingService); class LoggingService( [LogLevel(LogLevel.Info)] ILogger infoLogger, [LogLevel(LogLevel.Error)] ILogger errorLogger) { // 使用不同级别的日志器 }高级配置技巧1. 属性参数索引配置每个注册方法都可以指定参数索引默认为0用于确定从哪个参数读取元数据// 从第二个参数读取顺序信息 .OrdinalAttributeMyAttribute(1) // 从第一个参数读取标签信息默认 .TagAttributeMyAttribute() // 从泛型参数读取类型信息 .TypeAttributeMyAttribute()2. 组合使用多个属性可以在同一个成员上使用多个自定义属性class ComplexService { [MyTag(cache), MyOrdinal(2), MyType(typeof(RedisCache))] public ICache Cache { get; set; } [MyTag(db), MyOrdinal(1)] public IDatabase Database { get; set; } }3. 继承标准属性可以继承Pure.DI的标准属性来添加额外功能[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] class ValidatedDependencyAttribute(string tag, ValidationType validation ValidationType.None) : TagAttribute(tag) { public ValidationType Validation { get; } validation; } enum ValidationType { None, Required, Optional }最佳实践建议1. 保持属性简洁// ✅ 推荐职责单一 [Database(Primary)] public IDbConnection PrimaryDb { get; set; } // ❌ 避免功能混杂 [Database(Primary, ConnectionType Sql, Timeout 30)] public IDbConnection Db { get; set; }2. 使用有意义的标签值// ✅ 推荐语义明确 [Environment(Production)] public IConfiguration Config { get; set; } // ❌ 避免魔法字符串 [Tag(env1)] public IConfiguration Config { get; set; }3. 合理使用顺序属性class InitializationService { [MyOrdinal(1)] // 第一步初始化配置 public IConfiguration Config { get; set; } [MyOrdinal(2)] // 第二步初始化日志 public ILogger Logger { get; set; } [MyOrdinal(3)] // 第三步初始化数据库 public IDatabase Database { get; set; } }常见问题解答Q: 自定义属性和标准属性有什么区别A: 自定义属性提供了更大的灵活性可以根据具体业务需求定义专属的元数据属性而标准属性是框架内置的通用解决方案。Q: 什么时候应该使用通用属性A: 当需要同时管理标签、顺序和类型信息并且希望减少属性数量时通用属性是最佳选择。Q: 属性配置会影响性能吗A: 不会。Pure.DI在编译时处理所有属性配置运行时性能与使用标准属性完全相同。Q: 可以混合使用自定义属性和标准属性吗A: 可以但建议保持一致。混合使用会增加配置的复杂性降低代码可读性。总结Pure.DI的自定义属性功能为.NET依赖注入提供了前所未有的灵活性。通过合理使用自定义属性开发者可以创建领域特定的注入语义使代码更贴近业务逻辑减少配置重复通过通用属性简化元数据管理提高代码可读性使依赖关系更加清晰明确保持编译时验证所有配置都在编译时检查避免运行时错误无论是简单的标签标记还是复杂的元数据管理Pure.DI的自定义属性都能提供完美的解决方案。开始尝试自定义属性让你的依赖注入配置更加优雅和强大记住好的依赖注入配置应该像好的代码一样——清晰、简洁且易于维护。Pure.DI的自定义属性功能正是为此而生让你的.NET应用架构更加健壮和可扩展。【免费下载链接】Pure.DIPure DI for .NET项目地址: https://gitcode.com/gh_mirrors/pu/Pure.DI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考