HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Better ways to build a linq specification for querying or is this the only way?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thisspecificationlinqthewayswaybetterqueryingforonly

Problem

The code pretty much explains what I am doing here. Just wondering if anyone can think of a better way.

public class AttachmentQuery
{
    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// The type.
    /// The status.
    /// The sort.
    /// The order.
    /// The page.
    public AttachmentQuery(string type, string status, SortAttachment sort, SortOrder order, int? page)
    {
        IAttachmentSpecification specification = null;

        if (!string.IsNullOrEmpty(type))
        {
            specification = new AttachmentFileTypeSpecification(type);
        }

        if (!string.IsNullOrEmpty(status))
        {
            if (specification == null)
            {
                specification = new AttachmentStatusSpecification(status.AsEnum());
            }
            else
            {
                var spec = new AndSpecification(
                    specification, 
                    new AttachmentStatusSpecification(status.AsEnum())
                );

                specification = spec as IAttachmentSpecification;
            }
        }

        if (specification == null)
        {
            specification = new AttachmentSpecification();
        }

        specification.Page = page;
        specification.Limit = Setting.AttachmentPageLimit.Value;
        specification.Sort = sort;
        specification.Order = order;

        this.Specification = specification;
    }

    /// 
    /// Gets or sets the specification.
    /// 
    /// The specification.
    public IAttachmentSpecification Specification
    {
        get;
        private set;
    }
}


Source.

How it is used.

Solution

I would definitely write it differently but exact result depends on whether your AndSpecification supports only two parameters or it can accept IEnumerable of attachments.

If it has two parameters and you expect to nest those AndSpecifications if you will have more specs to compose then I would write something like this:

var typeSpecification = string.IsNullOrEmpty(type) ? null : new AttachmentFileTypeSpecification(type);
var statusSpecification = string.IsNullOrEmpty(status) ? null : new AttachmentStatusSpecification(status.AsEnum());
var specificationsToCompose = new IAttachmentSpecification[] {typeSpecification, statusSpecification};

var composedSpecification = specificationsToCompose
                     .Aggregate((IAttachmentSpecification) null, (accumulator, currentSpec) =>
                         {
                             if (accumulator != null && currentSpec != null) return new AndSpecification(accumulator, currentSpec);
                             return accumulator ?? currentSpec;
                         })
                      ?? new AttachmentSpecification();

...

this.Specification = composedSpecification;

Code Snippets

var typeSpecification = string.IsNullOrEmpty(type) ? null : new AttachmentFileTypeSpecification(type);
var statusSpecification = string.IsNullOrEmpty(status) ? null : new AttachmentStatusSpecification(status.AsEnum<AttachmentStatus>());
var specificationsToCompose = new IAttachmentSpecification[] {typeSpecification, statusSpecification};

var composedSpecification = specificationsToCompose
                     .Aggregate((IAttachmentSpecification) null, (accumulator, currentSpec) =>
                         {
                             if (accumulator != null && currentSpec != null) return new AndSpecification<Attachment>(accumulator, currentSpec);
                             return accumulator ?? currentSpec;
                         })
                      ?? new AttachmentSpecification();

...

this.Specification = composedSpecification;

Context

StackExchange Code Review Q#762, answer score: 4

Revisions (0)

No revisions yet.