Unity容器条件依赖注入实现方案咨询(含API场景问题)
解决Unity容器下Google/Yelp服务的条件依赖注入问题
看起来你遇到的核心问题是共享的WebPortalApiClient实例被Google初始化时覆盖了AccessToken,导致Yelp调用失败——因为默认情况下Unity会注册单例实例,两个服务共用同一个对象,Google的Init调用把AccessToken设为null,直接影响了Yelp的后续使用。下面给出两种基于Unity的解决方案,帮你彻底解决这个问题:
方案一:使用Unity命名注册(Named Registrations)
给Google和Yelp分别注册独立配置好的IWebPortalApiClient实例,确保两个服务拿到的是完全隔离的对象。
步骤1:注册命名的ApiClient实例
在Unity容器配置中,分别创建Google和Yelp专属的ApiClient实例,提前完成初始化:
// 注册Google专用的ApiClient container.RegisterType<IWebPortalApiClient, WebPortalApiClient>("GoogleApiClient", new InjectionFactory(_ => { var serverString = ConfigHelper.GetAppSetting(ConfigConstants.APIServerType); var server = (WebPortalServer)Enum.Parse(typeof(WebPortalServer), serverString, true); var apiClient = new WebPortalApiClient(); // Google不需要AccessToken,直接初始化服务器即可 apiClient.Init(server); return apiClient; }) ); // 注册Yelp专用的ApiClient container.RegisterType<IWebPortalApiClient, WebPortalApiClient>("YelpApiClient", new InjectionFactory(_ => { var serverString = ConfigHelper.GetAppSetting(ConfigConstants.APIServerType); var server = (WebPortalServer)Enum.Parse(typeof(WebPortalServer), serverString, true); var apiClient = new WebPortalApiClient(); var yelpToken = ConfigHelper.GetAppSetting(ConfigConstants.YelpApiKey); apiClient.Init(server, yelpToken); return apiClient; }) );
步骤2:给Google/Yelp类指定注入对应的实例
注册业务类时,明确指定要注入的命名ApiClient:
// 给Google类注入Google专用的ApiClient container.RegisterType<IGoogle, Google>( new InjectionConstructor(container.Resolve<IWebPortalApiClient>("GoogleApiClient")) ); // 给Yelp类注入Yelp专用的ApiClient container.RegisterType<IYelp, Yelp>( new InjectionConstructor(container.Resolve<IWebPortalApiClient>("YelpApiClient")) );
这样Google和Yelp各自拿到独立的ApiClient实例,再也不会互相干扰配置。
方案二:使用工厂模式(更符合单一职责)
把ApiClient的创建逻辑封装到工厂类中,让Google和Yelp通过工厂获取自己需要的实例,代码结构更清晰。
步骤1:定义工厂接口和实现
public interface IWebPortalApiClientFactory { IWebPortalApiClient CreateGoogleApiClient(); IWebPortalApiClient CreateYelpApiClient(); } public class WebPortalApiClientFactory : IWebPortalApiClientFactory { public IWebPortalApiClient CreateGoogleApiClient() { var serverString = ConfigHelper.GetAppSetting(ConfigConstants.APIServerType); var server = (WebPortalServer)Enum.Parse(typeof(WebPortalServer), serverString, true); var apiClient = new WebPortalApiClient(); apiClient.Init(server); return apiClient; } public IWebPortalApiClient CreateYelpApiClient() { var serverString = ConfigHelper.GetAppSetting(ConfigConstants.APIServerType); var server = (WebPortalServer)Enum.Parse(typeof(WebPortalServer), serverString, true); var apiClient = new WebPortalApiClient(); var yelpToken = ConfigHelper.GetAppSetting(ConfigConstants.YelpApiKey); apiClient.Init(server, yelpToken); return apiClient; } }
步骤2:修改Google/Yelp的构造函数
让业务类依赖工厂,而不是直接依赖ApiClient:
public class Google : IGoogle { private readonly IWebPortalApiClient _webPortalApiClient; public string GoogleKey { get; private set; } public Google(IWebPortalApiClientFactory factory) { this._webPortalApiClient = factory.CreateGoogleApiClient(); this.GoogleKey = $"&key={ConfigHelper.GetAppSetting(ConfigConstants.Googlekey)}"; } // 其他业务方法... } public class Yelp : IYelp { private readonly IWebPortalApiClient _webPortalApiClient; public Yelp(IWebPortalApiClientFactory factory) { this._webPortalApiClient = factory.CreateYelpApiClient(); } // 其他业务方法... }
步骤3:注册工厂和业务类
container.RegisterType<IWebPortalApiClientFactory, WebPortalApiClientFactory>(); container.RegisterType<IGoogle, Google>(); container.RegisterType<IYelp, Yelp>();
额外优化建议:重构WebPortalApiClient的初始化方式
当前的Init方法会让实例处于可变状态,很容易出现类似的覆盖问题。建议把初始化逻辑放到构造函数中,让实例创建时就处于稳定状态:
public class WebPortalApiClient : IWebPortalApiClient { public WebPortalServer WebPortalServer { get; } public string AccessToken { get; } // 用构造函数替代Init方法,确保实例不可变 public WebPortalApiClient(WebPortalServer server, string accessToken = null) { WebPortalServer = server; AccessToken = accessToken; } // 移除原来的Init方法 // 其他InvokeApi等方法保持不变... }
这样不管用命名注册还是工厂模式,都能在创建时直接传入参数,彻底避免后续修改实例状态的风险。
内容的提问来源于stack exchange,提问作者Mayank Bhuvnesh
相关产品推荐
相关产品推荐

