Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ExpressionSpecification public #2364

Closed
worthy7 opened this issue Jul 27, 2017 · 5 comments
Closed

Make ExpressionSpecification public #2364

worthy7 opened this issue Jul 27, 2017 · 5 comments
Assignees
Milestone

Comments

@worthy7
Copy link
Contributor

worthy7 commented Jul 27, 2017

Specifications are a really great idea. I'd like to use them more extensively.

  1. I would like to make them faster. I made this:
  public class Specification<T> : Abp.Specifications.Specification<T>
    {

        private Expression<Func<T, bool>> exp;

        public Specification(Expression<Func<T, bool>> expin) : base()
        {
            exp = expin;
        }


        public override Expression<Func<T, bool>> ToExpression()
        {
            return exp;
        }
    }

And it works well, Could you add this constructor to the Specification class? (Sorry I don't have 2017 so I cannot open and edit the project to do a PR)

It allows one to do the following

  public class CoreShipmentSpecificationProvider : IShipmentSpecificationProvider
    {
        public virtual ISpecification<出荷実績> GetAll()
        {
            return new Specification<出荷実績>((shipment) => shipment.IsDeleted == false);
        }

        public virtual ISpecification<出荷実績> GetEditable()
        {
            return new Specification<出荷実績>((shipment) => (shipment.IsDeleted == false && shipment.請求書ID == null && shipment.納品書印刷フラグ == false && shipment.請求書明細印刷フラグ == false));
        }

        public virtual ISpecification<出荷実績> GetDeletable()
        {
            return GetAll().And(new Specification<出荷実績>((shipment) => shipment.IsDeleted == false));
            
        }
    }
@hikalkan
Copy link
Member

Hi,

Thank you for your suggestion. However, it drops the value of specifications. If you want to pass arbitrary expressions, why not directly using LINQ extensions like GetAll().Where((shipment) => shipment.IsDeleted == false); which is shorter.

@hikalkan
Copy link
Member

Actually there is ExpressionSpecification class which is explicitly does what you want: https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/src/Abp/Specifications/ExpressionSpecification.cs#L20

@worthy7
Copy link
Contributor Author

worthy7 commented Jul 27, 2017

internal sealed class ExpressionSpecification : Specification

:/ So I can't use it.

What I am trying to achieve is something that can dynamically, according to the users role, adjust the filters for each entity in a complex way.

It seems my options are to either create separate Services for each user role, and have a core service as the parent. Or I create different specifications, and change them depending on the role of the user, and use an interface to allow the Spec to be DI'ed into the service without and code changes in the service layer.

For example, the user want's to edit. But I need to check if they can edit this entity.
The permission depends on the user role, and a few other complex things of the entity, or if they are admin then they can do anything.

So I could write a giant if statement inside the serivce layer (CheckCanEdit(Entitiy entity, UserInfo ui) or I can create separate services, and inject the right one depending on the role, or I can do a similar thing, but with specifications.

Services represent ACTIONS mainly, taken on entities. The actions can be permitted with AbpAuthorize.
Specifications represent FILTERS on entities. And can be made to apply to an action too (by creating many specifications).

The actions between admin and non-admin are basically the same. Who can do it changes. For example, shipments older than 3 days can be edited by an admin, but not by a non-admin. How do you suggest implementing such logic?

@hikalkan
Copy link
Member

We can make ExpressionSpecification public. I don't remember why it's internal. It was contributed by the community.

@hikalkan hikalkan changed the title [FR] Specification changes Make ExpressionSpecification public Jul 27, 2017
@hikalkan hikalkan added this to the v2.3 milestone Jul 27, 2017
@worthy7
Copy link
Contributor Author

worthy7 commented Jul 27, 2017

Can someone suggest an answer to my final question please?

For example, shipments older than 3 days can be edited by an admin, but not by a non-admin. How do you suggest implementing such logic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants