The code can be clean, it should be clean!
Our day-by-day development life consists of very exciting new features implementation, but from time to time we need to get back to our old code.
Recently we were introducing Revision and RevisionFile entities CRUD commands support, so it was necessary to update the following code:
public class EntityLifecycleEventToMessageMapperRepository : IEntityLifecycleEventToMessageMapperRepository
{
private readonly List<IEntityEventArgsToMessageMapper> _mappers =
new List<IEntityEventArgsToMessageMapper>();
public EntityLifecycleEventToMessageMapperRepository(IMessageGateway gateway)
{
_mappers = new List<IEntityEventArgsToMessageMapper>
{
new AttachmentEventArgsToMessageMapper(gateway),
new AttachmentFileEventArgsToMessageMapper(gateway),
new BugEventArgsToMessageMapper(gateway),
new BuildEventArgsToMessageMapper(gateway),
new CommentEventArgsToMessageMapper(gateway),
new CompanyEventArgsToMessageMapper(gateway),
new ContactEventArgsToMessageMapper(gateway),
new CustomActivityEventArgsToMessageMapper(gateway),
new CustomFieldEventArgsToMessageMapper(gateway),
new CustomReportEventArgsToMessageMapper(gateway),
new EntityStateEventArgsToMessageMapper(gateway),
new FeatureEventArgsToMessageMapper(gateway),
new ImpedimentEventArgsToMessageMapper(gateway),
new IterationEventArgsToMessageMapper(gateway),
new MessageEventArgsToMessageMapper(gateway),
new MessageUidEventArgsToMessageMapper(gateway),
new MilestoneEventArgsToMessageMapper(gateway),
new ProcessEventArgsToMessageMapper(gateway),
new ProcessPracticeEventArgsToMessageMapper(gateway),
new ProgramEventArgsToMessageMapper(gateway),
new ProjectEventArgsToMessageMapper(gateway),
new ProjectMemberEventArgsToMessageMapper(gateway),
new ReleaseEventArgsToMessageMapper(gateway),
new RequestEventArgsToMessageMapper(gateway),
new RequesterEventArgsToMessageMapper(gateway),
new RoleEventArgsToMessageMapper(gateway),
new RoleEffortEventArgsToMessageMapper(gateway),
new RoleEntityTypeEventArgsToMessageMapper(gateway),
new RuleEventArgsToMessageMapper(gateway),
new SolutionEventArgsToMessageMapper(gateway),
new TagEventArgsToMessageMapper(gateway),
new TagBundleEventArgsToMessageMapper(gateway),
new TaskEventArgsToMessageMapper(gateway),
new TeamEventArgsToMessageMapper(gateway),
new TermEventArgsToMessageMapper(gateway),
new TestCaseEventArgsToMessageMapper(gateway),
new TestPlanEventArgsToMessageMapper(gateway),
new TestPlanRunEventArgsToMessageMapper(gateway),
new TimeEventArgsToMessageMapper(gateway),
new UserEventArgsToMessageMapper(gateway),
new UserStoryEventArgsToMessageMapper(gateway)
};
}
You see? This long list should be updated everytime when a new mapper related to specified
entities introduced, which is not funny.
After a short discussion the code above was refactored into the following form:
public class EntityLifecycleEventToMessageMapperRepository : IEntityLifecycleEventToMessageMapperRepository
{
private readonly IEntityEventArgsToMessageMapper[] _mappers;
private static readonly Type[] MessageMapperTypes;
static EntityLifecycleEventToMessageMapperRepository()
{
MessageMapperTypes = ScanForMessageMappers();
}
public EntityLifecycleEventToMessageMapperRepository()
{
_mappers = MessageMapperTypes.Select(ObjectFactory.GetInstance).Cast<IEntityEventArgsToMessageMapper>().ToArray();
}
private static Type[] ScanForMessageMappers()
{
return Assembly.GetExecutingAssembly().GetTypes()
.Where(x => typeof (IEntityEventArgsToMessageMapper).IsAssignableFrom(x))
.Where(x => !x.IsAbstract)
.ToArray();
}
So now we won't touch this class anymore: it will find all IEntityEventArgsToMessageMapper implementations. All what we need is to define a new one and it will be automatically picked up.