views:

118

answers:

2

Hi.

I need some help with DLL architecture / design patterns / OO.

I have been learning about class factory design patterns as a solution to my current challenge and could use some feedback at this point.

I have three classes that are custom wrappers for ASP.NET 2.0's ProfileProvider, MembershipProvider, and RoleProvider.

I'd like to implement a way of calling each that is reasonably simple and intuitive for developers. Something to the effect of:

Object obj = new Users().Permissions.CreateRole();
Object obj = = new Users().Membership.CreateUser();
Object obj = = new Users().Profile.GetUserProfile();

The examples I have read on how to do this using an abstract class factory (if, indeed, this is the way to go) are somewhat confusing (I have been working my way round this link ).

Any suggestions on best practices as to how to get started? Or, even better, code illustrations? :)

Thanks in advance...

A: 

It looks to me that you're creating an abstraction on top of an abstraction for no real purpose and with no real benefit. I have issues with the way ASP.NET Providers were implemented (for testability), but I addressed that in another way.

What I did was create a class that Wrapped the MembershipProvider and implemented an interface. All it does is pass methods calls to the MembershipProvider, but it allows me to rely on the interface instead of the implementation. In my tests, I can swap out IMembershipProvider for a mocked version.

edit, sample code:

IMembershipService

// Membership service that just provides Create/Delete
public interface IMembershipService
{
    IMembershipUser CreateUser(string username, string password);
    void DeleteUser(string username);
}

and IMembershipUser

// IMembershipUser that provides a lot of the necessary details
public interface IMembershipUser
{
    string UserName { get; }
    bool IsApproved { get; }
    bool IsLockedOut { get; }
    string Email { get; }
    DateTime LastLoginDate { get; }
    DateTime CreationDate { get; }
    bool ChangePassword(string oldPassword, string newPassword);
    string ResetPassword();
    Guid UserID { get; }
}

and a simple wrapper for ASP.NET provider:

public class MembershipWrapper : IMembershipFactory
{
    #region IMembership Members

    public IMembershipUser CreateUser(string email, string password)
    {
        var user = System.Web.Security.Membership.CreateUser(email, password, email);
        return new MembershipUserWrapper(user);
    }

    public void DeleteUser(string userName)
    {
        System.Web.Security.Membership.DeleteUser(userName);
    }

    #endregion
}

and MembershipUser

    public class MembershipUserWrapper : IMembershipUser
{
    private MembershipUser _User;
    public MembershipUserWrapper(MembershipUser user)
    {
        _User = user;
    }
    #region IMembershipUser Members

    public string ResetPassword()
    {
        return _User.ResetPassword();
    }

    public bool ChangePassword(string oldPassword, string newPassword)
    {
        return _User.ChangePassword(oldPassword, newPassword);
    }

    public string UserName
    {
        get { return _User.UserName; }
    }

    public bool IsApproved
    {
        get { return _User.IsApproved; }
    }

    public bool IsLockedOut
    {
        get { return _User.IsLockedOut; }
    }

    public string Email
    {
        get { return _User.Email; }
    }

    public DateTime LastLoginDate
    {
        get { return _User.LastLoginDate; }
    }

    public DateTime CreationDate
    {
        get { return _User.CreationDate; }
    }

    public Guid UserID
    {
        get { return (Guid)_User.ProviderUserKey; }
    }

    #endregion
}

Very simple implementation, but you can go to town with it.

statichippo
Thanks for your response statichippo. If it is not too much to ask, would you mind providing a sketched / skeletal code example so I can get a better handle on how you attacked this? Thanks again.
Code Sherpa
Thanks for your response and code-post Statichippo. The facade pattern posted by Jamie is closer to the mark for this particular effort but your code was very helpful. Thanks again.
Code Sherpa
A: 

The APIs for the membership provider classes are pretty straightforward and I don't think there's much to be gained by wrapping them. I think what you're looking for is the facade pattern. Basically you would create a class that encapsulates the user management activities for your application and hides the internal implementation. Calls to the class might look like:

userService.CreateAdminUser("keith", "godchaux");

the UserService class would use the membership provider to create a new user and assign the admin role to them.

Jamie Ide
Thanks Jamie, that is in fact exactly what I was looking for. Very much appreciated.
Code Sherpa