6
\$\begingroup\$

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

public class AttachmentQuery
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AttachmentQuery"/> class.
    /// </summary>
    /// <param name="type">The type.</param>
    /// <param name="status">The status.</param>
    /// <param name="sort">The sort.</param>
    /// <param name="order">The order.</param>
    /// <param name="page">The page.</param>
    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<AttachmentStatus>());
            }
            else
            {
                var spec = new AndSpecification<Attachment>(
                    specification, 
                    new AttachmentStatusSpecification(status.AsEnum<AttachmentStatus>())
                );

                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;
    }

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

Source.

How it is used.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

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<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;
\$\endgroup\$
1
  • \$\begingroup\$ Thats a good idea, I will probably end up trying this out. \$\endgroup\$
    – Mike Geise
    Feb 15, 2011 at 9:23
3
\$\begingroup\$

How about adding an extension method to IAttachmentSpecification, such as

public static class AttachmentSpecificationExtensions
{
     public static IAttachmentSpecification And(this IAttachmentSpecification orig, IAttachmentSpecification spec)
     {
         if (orig is NullAttachmentSpecification))
         {
             return spec ?? orig;
         }

         if (spec == null || spec is NullAttachmentSpecification)
         {
             return orig;
         }

         return (IAttachmentSpecification) new AndSpecification<Attachment>(specification, orig);
     }
}

public class NullAttachmentSpecification : AttachmentSpecification
{
} 

Now you can write your AttachmentQuery constructor as

public AttachmentQuery(string type, string status,
    SortAttachment sort, SortOrder order, int? page)
{
    var statusSpec = string.IsNullOrEmpty(status) 
            ? new NullAttachmentSpecification()
            : new AttachmentStatusSpecification(status.AsEnum<AttachmentStatus>())
    var typeSpec = string.IsNullOrEmpty(type) 
            ? new NullAttachmentSpecification()
            : new AttachmentFileTypeSpecification(type)

    Specification = statusSpec.And(typeSpec);

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

It would seem more obvious to me what the intent was here. Plus it would seem more extensible if you add other types of AttachmentSpecification later.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.