I am trying to understand how and where to implement domain model factories. I have included my Company aggregate as a demo of how I have done it.
I have included my design decisions at the end - I would appreciate any comments, suggestions, critique on those points.
The Company domain model:
public class Company : DomainEntity, IAggregateRoot
{
private string name;
public string Name
{
get
{
return name;
}
private set
{
if (String.IsNullOrWhiteSpace(value))
{
throw new ArgumentOutOfRangeException("Company name cannot be an empty value");
}
name = value;
}
}
internal Company(int id, string name)
{
Name = name;
}
}
The CompanyFactory domain factory:
This class is used to ensure that business rules and invariants are not violated when creating new instances of domain models. It would reside in the domain layer.
public class CompanyFactory
{
protected IIdentityFactory<int> IdentityFactory { get; set; }
public CompanyFactory(IIdentityFactory<int> identityFactory)
{
IdentityFactory = identityFactory;
}
public Company CreateNew(string name)
{
var id = IdentityFactory.GenerateIdentity();
return new Company(id, name);
}
public Company CreateExisting(int id, string name)
{
return new Company(id, name);
}
}
The CompanyMapper entity mapper:
This class is used to map between rich domain models and Entity Framework data entities. It would reside in infrastructure layers.
public class CompanyMapper : IEntityMapper<Company, CompanyTable>
{
private CompanyFactory factory;
public CompanyMapper(CompanyFactory companyFactory)
{
factory = companyFactory;
}
public Company MapFrom(CompanyTable dataEntity)
{
return DomainEntityFactory.CreateExisting(dataEntity.Id, dataEntity.Name);
}
public CompanyTable MapFrom(Company domainEntity)
{
return new CompanyTable()
{
Id = domainEntity.Id,
Name = domainEntity.Name
};
}
}
The
Companyconstructor is declared asinternal.
Reason: Only the factory should call this constructor.internalensures that no other layers can instantiate it (layers are separated by VS projects).The
CompanyFactory.CreateNew(string name)method would be used when creating a new company in the system.
Reason: Since it would not have been persisted yet, an new unique identity will need to be generated for it (using theIIdentityFactory).The
CompanyFactory.CreateExisting(int id, string name)method will be used by theCompanyRepositorywhen retrieving items from the database.
Reason: The model would already have identity, so this would need to be supplied to the factory.The
CompanyMapper.MapFrom(CompanyTable dataEntity)will be used by theCompanyRepositorywhen retrieving data from persistence.
Reason: Here Entity Framework data entities need to be mapped into domain models. TheCompanyFactorywill be used to create the domain model to ensure that business rules are satisfied.The
CompanyMapper.MapFrom(Company domainEntity)will be used by theCompanyRepositorywhen adding or updating models to persistence.
Reason: Domain models need to be mapped straight onto data entity properties so that Entity Framework can recognise what changes to make in the database.
Thanks