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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:00:03