I wanted to investigate using LINQ to write constraints "OCL-style".   I made a "minimal language" and added a new NamedDomainClass called Property, embedded in ExampleElement.  Then I wrote the following validation method to check that all of the Properties attached to an ExampleElement are uniquely named:

[ValidationState(ValidationState.Enabled)]

public partial class ExampleElement

{

    [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]

    private void TestExampleElement(ValidationContext context)

    {

        var propnames = from p in this.Properties select p.Name;

        var distinctnames = propnames.Distinct<string>();

        if (propnames.Count<string>() != distinctnames.Count<string>())

        {

            context.LogError("Non-unique property names", "Error 1");

        } 

    }

} 

 

A lot tighter than writing it in good old C#, I think.  Then I thought about "flattened sets", i.e. navigating across more than one relationship and creating a single collection containing the results.  So I created SubProperty embedded in Property, and extended the constraint like this:

 

[ValidationState(ValidationState.Enabled)]

public partial class ExampleElement

{

    [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]

    private void TestExampleElement(ValidationContext context)

    {

        var propnames = from p in this.Properties select p.Name;

        var distinctnames = propnames.Distinct<string>();

        if (propnames.Count<string>() != distinctnames.Count<string>())

        {

            context.LogError("Non-unique property names", "Error 1");

        }

 

        var subproperties = this.Properties.Aggregate(Enumerable.Empty<SubProperty>(),

                                                        (agg, p) => agg.Union<SubProperty>(p.SubProperties));

        var subpropnames = from p in subproperties select p.Name;

        var distinctsubpropnames = subpropnames.Distinct<string>();

 

        if (subpropnames.Count<string>() != distinctsubpropnames.Count<string>())

        {

            context.LogError("Non-unique sub property names", "Error 2");

        }

    }

}

 

Not bad: but that line to calculate and flatten the subproperties is a bit complicated.  So, inspired by OCL, I defined a new extension method like this:

 

public static class C

{

    public static IEnumerable<U> Collect<T, U>(this IEnumerable<T> source, Func<T, IEnumerable<U>> func)

    {

        return source.Aggregate(Enumerable.Empty<U>(), (agg, p) => agg.Union<U>(func(p)));

    }

}

 

And now the subproperties line looks like this:

 

var subproperties = this.Properties.Collect(p => p.SubProperties);

 

I think I may be using that Collect method again!