How can I improve this design so that I don’t need to dynamically scan classes at runtime?

I’m in the middle of a redesign on the part of my current project that deals with user permissions and authorization. I have an interface named IUserPermissions that encapsulates this information.

One part of a user’s permissions are the Roles which they are a member of. I’m trying not to violate the Open/Closed Principle by adding every possible role to IUserPermissions as a property like this:

interface IUserPermissions {
    bool IsAdmin { get; set; }
    bool IsDeveloper { get; set; }
    // Many more...Yuck.
}

I feel that having an interface like this would suit the OCP better:

interface IUserPermissions {
    ICollection<IRole> Roles { get; }
    bool IsInRole<T>() where T : IRole;  /* (For convenience; Would probably be
                                             implemented as an extension method) */
}
interface IRole {
    string Name { get; }
}
public class AdminRole : IRole {
    public string Name { get { return "Admin"; } }
}

Where I’m falling down is how to implement something like this. I’m using the ASP.NET Roles API as the backing store, meaning I’ll be given a string[] of role names for the user. My IUserPermissions implementation would have to start with this collection of strings and somehow work backwards, then instantiate a bunch of appropriate IRoles to populate the Roles property.

This could be done by scanning the assembly for IRoles with a parameterless constructor, instantiating them, and reading their Name property, but…ugh. How can I fix this design so that I don’t have to do this?

1

Have you considered creating an enum with all possible roles? Sure, if in the future you require a new role to be added, you’ll have to modify the enum, which would break OCP, but I honestly do not believe it is worth it to go to such lengths just to avoid something that simple.

P.S.: Plus, you can use the Enum.Parse method to populate your collection from the array of strings.

2

I don’t know .NET buy I will explain myself with Java. You can see it as pseudocode.

You don’t have to instantiate concrete roles inside the IUserPermissions implementors, nor you need have a list of all roles or role names.

Look:

package permissions;

import java.util.Collection;

public interface IUserPermissions {
    public Collection<IRole> getRoles(); 
    public void addRole(IRole role);     // add a role to the collection
    public void removeRole(IRole role);  // remove a role from the collection
    public boolean isInRole(IRole role); 
    public boolean isInRole(String roleName);
}

Implementor of public boolean isInRole(IRole role); just checks if role is present in the collection using the constains method or similar.

The difference is here is this:

Implementor of public boolean isInRole(String roleName); traverses the collection comparing the roleName string with each role’s getName() method.

If all you have is an array of role names, you use isInRole(String roleName), otherwise you use isInRole(IRole roleName)

For this to work you must ensure that no two roles have the same name. You can do that with Factory class.

It’s ok for factory classes to be coupled to concrete classes. Their work is to be the only place where “new” is executed, so the rest of the system is decoupled from concrete classes.

1

Why not code the mapping (Role as String -> Role as concrete IRole type) in a Factory class?

public class RoleFactory
{
    public IEnumerable<IRole> CreateRoles(IEnumerable<String> roleStrings)
    {
        return roleStrings.Select(item => this.CreateRole(item)).ToList();
    }

    public IRole CreateRole(String roleString)
    {
        IRole result = null;

        switch(roleString)
        {
            case "Viewer":
                result = new ViewerRole();
                break;

            case "Admin":
                result = new AdminRole();
                break;

            case "Monkey":
                result = new MonkeyRole();
                break;

            default:
                throw new ArgumentException("Unexpected Role String");
        }

        // extra Defensive Programming
        if (result == null)
        {
            throw new InvalidOperationException("Role mapping is broken.");
        }

        return result;
    }
}

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật