Craig
Craig

Reputation: 391

Castle Windsor Factory implementation

I am using a Typed Factory supplied by Windsor Castle DI container. I am quite new to DI containers, so am after a bit of guidance with my solution.

Here is my implementation:

*updated registration & DB call

public interface IAgent {    }
public class Agent : IAgent     {    }

public interface IAgentFactory     
{
    IAgent Create();
    IAgent Create(int agentId);
    IAgent Create(AgentDTO agentDTO);
}

class AgentFactory : IAgentFactory     
{        
    public IAgent Create()         
    {            
        return InitNewEntity(new Agent());
    }
    public IAgent Create(int agentId, IDBContext dbContext) //Not happy with this, as it's a dependency that isn't factored out :(    
    {
        return dbContext.GetAgent(agentId);
    }
    public IAgent Create(AgentDTO agentDTO)
    {
         Agent agent = InitNewEntity(new Agent());
         agent.ParseDTO(agentDTO);
         return agent;
    }
    private IAgent InitNewEntity(IAgent agent)
    {
         agent.Username = "";        /// + other fields to initialise
         agent.DOB = DateTime.Now;   /// etc.
         return agent;
    }

...

Container.AddFacility<TypedFactoryFacility>()
            .Register( Component.For<IAgentFactory>()
                                .ImplementedBy<AgentFactory>());

which I'm using the following call to get some entities

IAgentFactory agentFactory = ViewModel.Container.Resolve<IAgentFactory>();

IAgent agent = agentFactory.Create();  //Creates new Agent entity
agent = agentFactory.Create(66, dbContext); //Looks up entity in database, don't like passing in a db context, another dependency
agent = agentFactory.Create(agentDTO);      //Creates Agent entity from DTO object

I have several concerns about this.

There are 3 possible scenarios regarding creating a new Agent,

1: Create a new agent from scratch

2: Create an agent using an existing DTO (Data Transfer Object)

3: Create an agent with a call to the database.

I decided to put all this functionality into a factory, as it seems to fit the bill, however, I am not entirely sure if this is the correct or best way to accomplish this.

The question is, is it possible to leverage all 3 Create scenarios into the DI container Register statement and omit the concrete factory implementation altogether, so that I no longer have an AgentFactory class, but only the IAgentFactory interface.

Another question I have regarding this implementation, is it possible to do a call, such that if I request an Agent entity, Windsor will first make a call to the factory and return the entity created from the factory, rather than create the entity without referencing the factory. ie.

IAgent agent = Container.Resolve<IAgent>(66);

With a Callstack:

Container -> AgentFactory -> Create(66) -> returns agent from factory.

Which Windsor will intercept and automatically use the factory to create the instance. However, I tried this and it didn't use the factory to create it, it just went ahead and created the Agent without referencing the factory.

I did have this, but it doesn't call the factory methods that I have defined.

Container.AddFacility<TypedFactoryFacility>()
            .Register(Component.For<IAgentFactory>().AsFactory(),
                      Component.For<IAgent>().ImplementedBy<Agent>());

Advice is appreciated, thank you.

Upvotes: 1

Views: 1776

Answers (1)

Crixo
Crixo

Reputation: 3070

Typed Factory is designed to create "behaviour" instance, not "data" instance.

You do not register into the container a "model" component, but compenent to work w/ the model. In other words you register into the container everything but the model.

You AgentFactory has to be registerted into the container, but that's not a "Typed Factory". You may use TF for "late dependency" purpose.

I prefer be more decoupled w/ my design and also more "single responsability" oriented. AgentFactory won't hide a repository (as per your Create from db) within the factory: I will pass a datareader as Create parameter instead.

Upvotes: 2

Related Questions