Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save darrencauthon/708929 to your computer and use it in GitHub Desktop.
Save darrencauthon/708929 to your computer and use it in GitHub Desktop.
This is a short example showing how one can use a separate class to determine which class should be used in which context.
public class CatalogContextDeterminer
{
private XPrincipal principal;
public CatalogContextDeterminer(XPrincipal principal)
{
principal = principal;
}
public Type GetCatalogContextType()
{
if (TheUserIsNotLoggedIn())
return typeof (NonMemberCatalogContext);
var memberType = GetTheCurrentUsersMemberType();
if (ThisIsAChapterMember(memberType))
return GetTheChapterPricingForThisMemberType(memberType);
else
return typeof (MemberCatalogContext);
}
// .. more here
}
public class CatalogContextRegistration : IServiceRegistration
{
public void Register(IServiceLocator locator)
{
locator.Register(() =>
{
var determiner = locator.Resolve<CatalogContextDeterminer>();
return locator.Resolve(determiner.GetCatalogContextType()) as ICatalogContext;
});
}
}
@darrencauthon
Copy link
Author

The catalog you get (i.e. the pricing, the products that are available, etc.) depends on whether you are signed in and your type. Then whenever someone requests that catalog out of the container, this logic is used to determine which one you get.

What this also does is make each of the catalog classes very simple. NonMemberCatalogContext only contains the logic necessary to get the products & prices for non-members, MemberCatalogContext for members, and so on. This is an alternative to having some sort of "CanProcess" method where the classes are also aware of the context in which they should be used (which, under SRP, they shouldn't have to handle).

It also makes testing as simple as:

Given I am not logged in
When I request product information
Then I should get the non-member pricing
// ^^ which will test that NonMemberCatalogContext is returned

Given I am logged in
And my member type is 'APPLE'
When I request product information
Then I should get the Apple pricing

Given I am logged in
And my member type is 'ORANGE'
When I request product information
Then I should get the Member pricing

// you get the point....

@darrencauthon
Copy link
Author

BTW, one more point:

This class got more complex later. Client came back and wanted different pricing than chapter or member, and then had special pricing considerations based on if you were creating an account versus if you were creating an order as a guest. All of that complexity and change stayed in one place.

I know this isn't the best example of an alternative to "CanProcess()," this is just the freshest example of using this pattern in my head. But it works for other situations, too, even those where multiple classes needed to be instantiated and called.

It's really nice to be able to ask the container, "Resolve the implementation for this interface" or "Resolve all implementations of this interface" and know that whatever you get back is relevant to your situation.

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