I want to model service like this
public class FooService
{
public GetById(ISecurityContext context, id)
{
//checking context has right to view
//calling Foo repository to getById
}
public Add(ISecurityContext context,Foo fooEntity)
{
//checking context has right to add
//calling Foo repository to add
}
}
In the above methods i want to pass different type of SecurityContext
So what i have did is
Public Interface ISecurityContext
{
}
UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }
}
SessionContext : ISecurityContext
{
public string SessionId {get ; set;}
}
So In my Account Service i have a method
public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
if(context is UsernamePasswordContext)
return GetAccountByUsernamePassword(context.Username,context.Password);
else if (context is SessionContext)
return GetAccountBySessionId(context.SessionId);
// more else if for different type of context
}
}
In the above code i didnt liked so many if else
So i tried introducing polymorphism
So in my ISecurityContext interface i added a GetAccount method which all sub class will implement
Public Interface ISecurityContext
{
Account GetAccount();
}
UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }
public Account GetAccount()
{
//call account service
GetAccountByUsernamePassword(this.Username,this.Password);
}
}
and my account service will become like this
public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
context.GetAccount();
}
}
But the problem here is that i am calling a service/repository from my UsernamePasswordContext POCO which voilates DDD
So what are other ways i can model this scenario.
I think you’re not far off from the solution. In this case, I would inject a factory into your
AccountServicethat would take on the responsibility of theif..then..else. Then, the factory could use one of many possible solutions.One change I would make right off is I would make your AccountService implement an interface which should make it easier to inject later. Assuming you’re using some IOC container, you shouldn’t have to worry too much about dependencies because you’re letting the container handle all that.
Here are the pieces you already had, with some minor ajustments:
Here’s your account service along with it’s implementation:
So, you can see here that I’ve injected an
IAccountFactorythat will handle the actual creation (retrieval, whatever) of theAccountobject. All we care about at this point is that the account gets created/retrieved… we don’t care about how.There are a few ways you can implement a factory like this. One way is to use a type of strategy pattern where you have a list of widgets that know how to resolve an account. Then you just pick the widget (strategy) that matches and execute it. Something similar to this would be a factory that uses an IOC or service locator to resolve a type that has been registered previously in application configuration.
In the way of an example, here’s one possible implementation of
IAccountFactoryusingCommonServiceLocator:My factory here goes out to the service locator context and grabs whatever resolver matches our security context. Here are a couple examples of possible resolvers:
The only thing left is to register the resolvers in your IOC container so that they can be found when the service locator tries to resolve them in the factory.