.NET Core中为嵌入DbUp代码文件注入Umbraco依赖的方法
解决DbUp代码脚本注入Umbraco依赖的问题
核心原因
DbUp默认通过无参构造函数实例化IScript实现类,无法直接支持带依赖注入的构造函数,这就是你遇到MissingMethodException的根本原因。要解决这个问题,需要让DbUp使用项目的DI容器来创建脚本实例。
具体解决方案
1. 实现自定义脚本激活器
创建一个实现IScriptActivator的类,利用Umbraco的IServiceProvider来解析脚本实例,替代DbUp的默认实例化逻辑:
public class DiScriptActivator : IScriptActivator { private readonly IServiceProvider _serviceProvider; public DiScriptActivator(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public object CreateInstance(Type type) { // 优先用DI容器解析实例,支持带参数的构造函数 return _serviceProvider.GetService(type) ?? Activator.CreateInstance(type); } }
2. 配置DbUp时启用自定义激活器
在构建DbUp升级器的代码中,替换默认的脚本激活器,同时传入Umbraco的服务提供者:
// 获取Umbraco的服务提供者,可在Umbraco项目中通过Current.Services或DI容器直接获取 var serviceProvider = ...; var upgrader = DeployChanges.To .SqlDatabase(connectionString) .WithScriptsAndCodeEmbeddedInAssembly(Assembly.GetExecutingAssembly()) // 绑定自定义激活器 .WithScriptActivator(new DiScriptActivator(serviceProvider)) .LogToConsole() .Build(); var result = upgrader.PerformUpgrade();
3. 注册脚本类到Umbraco DI容器
在Umbraco的Composer类中,将你的代码脚本类注册为DI服务,确保容器能解析到实例:
public class UpgradeScriptsComposer : IComposer { public void Compose(IUmbracoBuilder builder) { // 单个脚本注册 builder.Services.AddTransient<Code0001>(); // 批量注册所有IScript实现类(可选) var scriptTypes = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => typeof(IScript).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var type in scriptTypes) { builder.Services.AddTransient(type); } } }
4. 调整脚本类逻辑(按需)
如果需要在脚本中同时执行SQL和Umbraco服务操作,可直接在ProvideScript方法中调用注入的服务:
public class Code0001(IContentTypeService contentTypeService) : IScript { private readonly IContentTypeService _contentTypeService = contentTypeService; public string ProvideScript(Func<IDbCommand> dbCommandFactory) { // 执行Umbraco内容类型修改操作 var contentType = _contentTypeService.Get("BlogPost"); if (contentType != null) { contentType.Properties.Add(new ContentTypeProperty("NewProperty", "Umbraco.Textbox")); _contentTypeService.Save(contentType); } // 需要执行SQL的话返回对应脚本,不需要则返回空字符串 return "UPDATE SomeTable SET Updated = 1;"; } }
注意事项
- 确保DbUp执行升级时,Umbraco的DI容器已经完成初始化,避免出现服务无法解析的情况。
- 如果升级是在Umbraco启动前执行(比如独立升级工具),需要手动构建Umbraco的DI容器,不能依赖Umbraco的自动初始化流程。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

