I've written a program to populate a particular object from multiple data sources, however I'm not convinced I'm going about this in the right way:
- I have no idea which (if any) design pattern I have used (possibly abstract factory)!
- I really don't like the implementation as it doesn't feel right.
I appreciate that this is verging on a little obsessive as the program works and meets the requirements for extensibility, however... is there a pattern that could be applied to solve this problem more effectively? What's right about my implementation? What's inherently wrong with my implementation? What could be done better?
NB. Please don't worry about the implementation of the Provider.Load()
methods - it's the pattern I'm concerned about here.
class Program
{
static void Main(string[] args)
{
string xmlFileName = ConfigurationManager.AppSettings["CustomerLeadssXml"];
string csvFileName = ConfigurationManager.AppSettings["CustomerLeadssCsv"];
CustomerLeads customerLeadsFromXml = new CustomerLeads(new XmlCustomerLeadsProvider(xmlFileName));
customerLeadsFromXml.Load();
OutputCustomerLeads(customerLeadsFromXml);
Console.WriteLine("");
CustomerLeads customerLeadsFromCsv = new CustomerLeads(new CsvCustomerLeadsProvider(csvFileName));
customerLeadsFromCsv.Load();
OutputCustomerLeads(customerLeadsFromCsv);
Console.ReadKey();
}
static void OutputCustomerLeads(CustomerLeads customerLeads)
{
Console.WriteLine("CustomerLeads:");
foreach (CustomerLead customerLead in customerLeads.GetCustomerLeads())
{
Console.WriteLine("{0} {1} - {2}", customerLead.FirstName, customerLead.LastName, customerLead.EmailAddress);
}
Console.WriteLine("");
Console.WriteLine("CustomerLeadsSorted:");
foreach (CustomerLead customerLead in customerLeads.GetCustomerLeadsSorted())
{
Console.WriteLine("{0} {1} - {2}", customerLead.FirstName, customerLead.LastName, customerLead.EmailAddress);
}
}
}
public class CustomerLeads
{
private ICustomerLeadsProvider CustomerLeadsProvider { get; set; }
public CustomerLeads(ICustomerLeadsProvider customerLeadsProvider)
{
if (customerLeadsProvider == null)
throw new ArgumentException("CustomerLeadsProvider cannot be null", "customerLeadsProvider");
this.CustomerLeadsProvider = customerLeadsProvider;
}
public void Load()
{
this.CustomerLeadsProvider.Load();
}
public List<CustomerLead> GetCustomerLeads()
{
if (this.CustomerLeadsProvider.CustomerLeads == null)
return null;
return this.CustomerLeadsProvider.CustomerLeads.ToList<CustomerLead>();
}
public List<CustomerLead> GetCustomerLeadsSorted()
{
if (this.CustomerLeadsProvider.CustomerLeads == null)
return null;
return (from c in this.CustomerLeadsProvider.CustomerLeads
orderby c.LastName, c.FirstName, c.EmailAddress
select new CustomerLead()
{
FirstName = c.FirstName,
LastName = c.LastName,
EmailAddress = c.EmailAddress
}).ToList<CustomerLead>();
}
}
public interface ICustomerLeadsProvider
{
IEnumerable<CustomerLead> CustomerLeads { get; set; }
void Load();
}
public abstract class CustomerLeadsProvider : ICustomerLeadsProvider
{
public IEnumerable<CustomerLead> CustomerLeads { get; set; }
public abstract void Load();
protected bool IsValidFirstName(string firstName)
{
return !string.IsNullOrEmpty(firstName);
}
protected bool IsValidLastName(string lastName)
{
return !string.IsNullOrEmpty(lastName);
}
protected bool IsValidEmail(string emailAddress)
{
try
{
var mailAddress = new System.Net.Mail.MailAddress(emailAddress);
return true;
}
catch
{
return false;
}
}
}
public class XmlCustomerLeadsProvider : CustomerLeadsProvider
{
private string FileName { get; set; }
private XDocument CustomerLeadsXDocument { get; set; }
public XmlCustomerLeadsProvider(string fileName)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentException("FileName cannot be null or empty.", "fileName");
this.FileName = fileName;
}
public override void Load()
{
this.CustomerLeadsXDocument = XDocument.Load(FileName);
base.CustomerLeads = from c in CustomerLeadsXDocument.Descendants("CustomerLead")
where base.IsValidFirstName((string)c.Descendants("FirstName").FirstOrDefault())
&& base.IsValidLastName((string)c.Descendants("LastName").FirstOrDefault())
&& base.IsValidEmail((string)c.Descendants("Email").FirstOrDefault())
select new CustomerLead()
{
FirstName = (string)c.Descendants("FirstName").FirstOrDefault(),
LastName = (string)c.Descendants("LastName").FirstOrDefault(),
EmailAddress = (string)c.Descendants("Email").FirstOrDefault()
};
}
}
public class CsvCustomerLeadsProvider : CustomerLeadsProvider
{
private string FileName { get; set; }
public CsvCustomerLeadsProvider(string fileName)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentException("FileName cannot be null or empty.", "fileName");
this.FileName = fileName;
}
public override void Load()
{
this.CustomerLeads = from l in File.ReadAllLines(this.FileName).Skip(1)
let c = l.Split(',')
where base.IsValidFirstName(c[0])
&& base.IsValidLastName(c[1])
&& base.IsValidEmail(c[2])
select new CustomerLead
{
FirstName = c[0],
LastName = c[1],
EmailAddress = c[2]
};
}
}
<?xml version="1.0" encoding="utf-8"?>
<CustomerLeads>
<CustomerLead>
<FirstName>Paul</FirstName>
<LastName>Smith</LastName>
<Email>[email protected]</Email>
</CustomerLead>
<CustomerLead>
<FirstName>Nicole</FirstName>
<LastName>Farhi</LastName>
<Email>[email protected]</Email>
</CustomerLead>
<CustomerLead>
<FirstName>Raf</FirstName>
<LastName>Simons</LastName>
<Email>[email protected]</Email>
</CustomerLead>
</CustomerLeads>
FirstName,LastName,Email
Paul,Smith,[email protected]
Nicole,Farhi,[email protected]
Raf,Simons,[email protected]