gpt4 book ai didi

aspnetboilerplate - ABP 中 NRules 的属性注入(inject)

转载 作者:行者123 更新时间:2023-12-04 08:21:43 25 4
gpt4 key购买 nike

我正在使用 ABP Boilerplate 6.0 并将 NRules 与我们的平台集成。

  • 我能够使下面的规则起作用,但问题是我不能在规则条件中使用注入(inject)的“_questionResponseRepository”,因为只有在满足规则条件后,才会解决依赖关系。
  • 我想使用“_questionResponseRepository”从数据库中获取关键字列表,并在规则匹配条件
  • 中使用这些词

    电话号码
    public WasteManagementManager(                      
    IRepository<WasteBirthCertificateBlock, long> wasteBirthCertificateBlockRepository,
    IRepository<WasteBirthCertificateChain, long> wasteBirthCertificateChainRepository,
    ISession nRuleSession,
    ISessionFactory nRuleSessionFactory,
    ILogger log

    )
    {
    _wasteBirthCertificateBlockRepository = wasteBirthCertificateBlockRepository;
    _wasteBirthCertificateChainRepository = wasteBirthCertificateChainRepository;
    _nRuleSession = nRuleSession;
    _nRuleSessionFactory = nRuleSessionFactory;
    _log = log;
    }

    public void Trigger()
    {==>
    When I am in debug, _questionResponseRepository is NOT NUll. I'm trying inject it as a fact but that is not property injection .. I'm just trying one way or the other to get it working


    _nRuleSession.Insert(_questionResponseRepository);
    _nRuleSession.Fire();
    }
    规则代码
     namespace SagerSystems.AI.WasteManagements.NRules
    {
    [Name("Track Explosive Substances Rule")]
    public class TrackExplosiveSubstancesRule : Rule
    {
    private string[] _listOfExplosiveKeyWords = new string[] { "H3O", "N2" };
    public IRepository<QuestionResponse, long> _questionResponseRepository { get; set; }

    public TrackExplosiveSubstancesRule()
    {
    **This does NOT work** (the value remains null)
    Dependency()
    .Resolve(() => _questionResponseRepository);
    }

    public override void Define()
    {
    *This does work* but only after the rule fires)
    Dependency()
    .Resolve(() => _questionResponseRepository);

    When()
    .Match(() => questionResponseDto, c => CheckKeyWord(c));

    Then()
    .Do(ctx => Console.WriteLine(“Test Condition Works”))
    }

    private bool CheckKeyWord(QuestionResponseDto questionResponseDto)
    {
    ==> How do I user ‘questionResponseRepository’
    var isKeyWord=
    _listOfExplosiveKeyWords.Any(c => questionResponseDto.QuestionText.Contains(c));
    return isKeyWord;
    }
    }
    }

    最佳答案

    有几种方法可以在 NRules 的规则匹配条件中使用外部信息(在本例中是来自数据库的关键字)。

  • 将相应的存储库/服务注入(inject)到规则中。
    有两种方法可以将依赖项注入(inject)规则。在规则类的实例化期间,或在规则运行时通过 Dependency.Resolve DSL。正如您所指出的,由于 Dependency.Relsove 只能用于规则(操作)的右侧,因此不适合此用例。但是您仍然可以在规则实例化期间将依赖项注入(inject)到规则中。
    这里需要做的是将规则类型本身注册到容器中,实现一个 IRuleActivator 来通过该容器解析规则,并在加载规则时设置 RuleRepository.RuleActivator。如果存储库和规则都在同一个容器中注册,则规则将被注入(inject)依赖项(您可以使用属性或构造函数注入(inject),具体取决于您注册类型的方式)。然后你可以在表达式中使用依赖。
    我没有你所有的代码,所以假设它看起来像下面这样。这里我假设有一个 Keyword 的存储库可用于从数据库中获取关键字的实体。我也在使用构造函数注入(inject),但同样适用于属性注入(inject)。

  •     public class RuleActivator : IRuleActivator
    {
    private readonly IIocResolver _iocResolver;

    public RuleActivator(IIocResolver iocResolver)
    {
    _iocResolver = iocResolver;
    }

    public IEnumerable<Rule> Activate(Type type)
    {
    yield return (Rule)_iocResolver.Resolve(type);
    }
    }

    public class RulesEngineModule : AbpModule
    {
    public override void Initialize()
    {
    //Find rule classes
    var scanner = new RuleTypeScanner();
    scanner.AssemblyOf<TrackExplosiveSubstancesRule>();
    var ruleTypes = scanner.GetRuleTypes();

    //Register rule classes with the container
    foreach (var ruleType in ruleTypes)
    {
    IocManager.Register(ruleType);
    }

    //Load rules into the repository; use a rule activator to resolve rules via the container
    var repository = new RuleRepository {Activator = new RuleActivator(IocManager)};
    repository.Load(x => x.From(s => s.Type(ruleTypes)));

    //Compile rules into the factory
    var factory = repository.Compile();

    //Register session factory instance
    IocManager.IocContainer.Register(
    Component.For<ISessionFactory>().Instance(factory));

    //Register session as a delegate that creates a new instance from a factory
    IocManager.IocContainer.Register(
    Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>().CreateSession()).LifestyleTransient());
    }
    }

    [Name("Track Explosive Substances Rule")]
    public class TrackExplosiveSubstancesRule : Rule
    {
    private readonly IRepository<Keyword, long> _keywordRepository;

    public TrackExplosiveSubstancesRule(IRepository<Keyword, long> keywordRepository)
    {
    _keywordRepository = keywordRepository;
    }

    public override void Define()
    {
    QuestionResponseDto questionResponseDto = default;

    When()
    .Match(() => questionResponseDto, c => ContainsKeyword(c));

    Then()
    .Do(ctx => Console.WriteLine("Test Condition Works"));
    }

    private bool ContainsKeyword(QuestionResponseDto questionResponseDto)
    {
    var keywords = _keywordRepository.GetAll().ToList();
    var hasKeyWord = keywords.Any(keyword => questionResponseDto.QuestionText.Contains(keyword.Value));
    return hasKeyWord;
    }
    }
    然后在您的 Trigger 方法中或相应 Controller 中的某处:
        var dto = new QuestionResponseDto(...);
    _session.Insert(dto);
    _session.Fire();
  • 从规则引擎外部的存储库中检索关键字,并将它们作为事实插入到 session 中。这实际上是首选,因为您可以更好地控制与外部数据的交互。此外,您可以将关键字放入具有高效查找性能的数据结构中(例如 trie)。
    在这种情况下,您不需要规则激活器或向容器注册规则,就像选项 #1 一样,因为所有输入都作为事实出现在规则中,因此实际上没有外部依赖项。
    例如:

  •     public class KeywordSet
    {
    private readonly Keyword[] _keywords;

    public KeywordSet(IEnumerable<Keyword> keywords)
    {
    _keywords = keywords.ToArray();
    }

    public bool ContainsAny(string value)
    {
    return _keywords.Any(keyword => value.Contains(keyword.Value));
    }
    }

    [Name("Track Explosive Substances Rule")]
    public class TrackExplosiveSubstancesRule : Rule
    {
    public override void Define()
    {
    KeywordSet keywordSet = default;
    QuestionResponseDto questionResponseDto = default;

    When()
    .Match(() => keywordSet)
    .Match(() => questionResponseDto, c => keywordSet.ContainsAny(c.QuestionText));

    Then()
    .Do(ctx => Console.WriteLine("Test Condition Works"));
    }
    }
    然后在您的 Trigger 方法中或相应 Controller 中的某处:
        var keywords = _keywordRepository.GetAll().ToList();
    var keywordSet = new KeywordSet(keywords);
    _session.Insert(keywordSet);

    var dto = new QuestionResponseDto(...);
    _session.Insert(dto);
    _session.Fire();
  • 您也可以将存储库本身作为事实插入,然后在规则中匹配它,但我不建议这样做,所以我会坚持使用选项 #1 或 #2。
  • 关于aspnetboilerplate - ABP 中 NRules 的属性注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65469249/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com