Лучшие способы построить спецификация LINQ для запросов или это единственный способ?


Код очень многое объясняет то, что я делаю здесь. Просто интересно, если кто-нибудь может придумать лучшего способа.

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

Источник.

Как она используется.



743
5
задан 13 февраля 2011 в 09:02 Источник Поделиться
Комментарии
2 ответа

Я бы однозначно написать это по-разному, но точный результат зависит от вашего AndSpecification поддерживает только два параметра или он может принять тип IEnumerable вложений.

Если он имеет два параметра и вы планируете гнездо этих AndSpecifications если у вас будет больше спецификаций для создания, то я бы написал что-то вроде этого:

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;

3
ответ дан 14 февраля 2011 в 10:02 Источник Поделиться

Как насчет добавить метод расширения для IAttachmentSpecification, таких как

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

Теперь вы можете писать свой конструктор AttachmentQuery как

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

Мне представляется более очевидным, что умысел был здесь. Плюс казалось бы, более растяжимы, если вы добавите прочая AttachmentSpecification позже.

2
ответ дан 14 февраля 2011 в 12:02 Источник Поделиться