2

我有一个类,它有几个包含 OCL 表达式的字符串属性。我需要在 OCL 中查询这些对象,并且在该 OCL 中我需要评估其中一个属性中的 OCL 表达式。

这可以做到吗?

我想我正在寻找类似的 OCL 操作<<object>>.eval(<<string>>),其中<<string>>将在 的上下文中进行评估<<object>>,并且最好继承周围 OCL 中的任何 OCL 变量,因此它们可以被<<string>>.

作为一种解决方法,我想我可以添加一个代码派生的额外属性,该属性在对象的上下文中评估属性的 OCL(这可能就足够了)。

4

2 回答 2

2

您可以编写自定义 OCL 操作。这里有一个例子:

[EcoOclOperation(typeof(OclEcoId), true)]
public class OclEcoId : OclOperationBase
{
    /// <summary>
    /// Initialisation of the OCL funktion
    /// </summary>
    protected override void Init()
    {
        var parameter = new IOclType[1]
        {
            this.Support.ObjectType,
        };
        this.InternalInit("EcoId", parameter, this.Support.IntegerType);
    }

    /// <summary>
    /// Implementation of the OCL function
    /// </summary>
    /// <param name="parameters">OCL parameters</param>
    public override void Evaluate(IOclOperationParameters parameters)
    {
        var iObject = parameters.Values[0].Element as IObject;
        if (iObject != null && iObject.AsObject != null)
        {
            var ecoid = iObject.EcoID();
            this.Support.MakeNewInteger(parameters.Result, int.Parse(ecoid));
        }
    }
}

这样的操作必须像这样安装到 EcoSpace 中:

public static class OclInstaller
{
    /// <summary>
    /// InstallOclOperations
    /// </summary>
    /// <param name="ecoSpace">The EcoSpaceparam>
    public static void InstallOclOperations(EcoSpace ecoSpace)
    {
        if (ecoSpace != null)
        {
            var ocls = ecoSpace.GetEcoService<IOclService>();
            var eals = ecoSpace.GetEcoService<IActionLanguageService>();

            // Install all available operations in current assembly
            foreach (Type t in System.Reflection.Assembly.GetAssembly(typeof(OclInstaller)).GetTypes())
            {
                if (t.BaseType == typeof(OclOperationBase))
                {
                    var op = (OclOperationBase)Activator.CreateInstance(t);
                    eals.InstallOperation(op);

                    object[] attributes = t.GetCustomAttributes(typeof(EcoOclOperationAttribute), false);
                    if (attributes.Length == 1)
                    {
                        if ((attributes[0] as EcoOclOperationAttribute).IsQuery)
                        {
                            ocls.InstallOperation(op);
                        }
                    }
                    else
                    {
                        ocls.InstallOperation(op);
                    }
                }
            }
        }
        else
        {
            throw new NullReferenceException("Error in [InstallOclOperations]: EcoSpace is null.");
        }
    }
}

在 ecospace 的构造函数中调用此安装程序:

OclInstaller.InstallOclOperations(this);

令人惊讶的是,使用 MDriven 添加新的自定义 OCL 操作是多么容易。正如 Hans 所说,开箱即用评估 OCL 是不可能的,但您可以编写自己的评估器。但请退后一步,对实现功能的方式做出适当的架构决定。

您也可以添加自定义生态服务,但这是完全不同的故事。

于 2018-06-21T07:19:03.507 回答
1

无法从 ocl/eal 本身评估 ocl/eal。由于安全隐患和自修改代码真的很奇怪的论点,它已被建议但被否决。

MDriven for Visual Studio 中的简单解决方法是在您的超类上添加一个 Eval 方法 - 并在 c# 中实现它 - 并调用 ocl 或 eal 服务。

我想如果你想对结果采取行动,你可以让 Eval 方法返回一个 Collection(SuperClass) 或 SuperClass

于 2018-06-20T21:58:18.093 回答