Given the sample console application below:
QUESTION #1: Why does .Name() return typeof OranizationBuilder, but .Write() calls CorporationBuilder?
QUESTION #2: How to get .Name() to return typeof CorporationBuilder?
namespace MyCompany
{
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Environment.NewLine);
Factory.Organization()
.ID(33)
.Name("Oranization A")
.Write();
Console.WriteLine("\n----------------------------\n");
Factory.Corporation()
.Date(DateTime.Today) // Pass
.ID(44)
.Name("Company B")
// .Date(DateTime.Today) // Fail
.Write();
// QUESTION #1: Why does .Name() return typeof OranizationBuilder,
// but .Write() calls CorporationBuilder?
// QUESTION #2: How to get .Name() to return typeof CorporationBuilder?
Console.ReadLine();
}
}
/* Business Classes */
public abstract class Contact
{
public int ID { get; set; }
}
public class Organization : Contact
{
public string Name { get; set; }
}
public class Corporation : Organization
{
public DateTime Date { get; set; }
}
/* Builder */
public abstract class ContactBuilder<TContact, TBuilder>
where TContact : Contact
where TBuilder : ContactBuilder<TContact, TBuilder>
{
public ContactBuilder(TContact contact)
{
this.contact = contact;
}
private TContact contact;
public TContact Contact
{
get
{
return this.contact;
}
}
public virtual TBuilder ID(int id)
{
this.Contact.ID = id;
return this as TBuilder;
}
public virtual void Write()
{
Console.WriteLine("ID : {0}", this.Contact.ID);
}
}
public class OrganizationBuilder : ContactBuilder<Organization, OrganizationBuilder>
{
public OrganizationBuilder(Organization contact) : base(contact) { }
public virtual OrganizationBuilder Name(string name)
{
(this.Contact as Organization).Name = name;
return this;
}
public override void Write()
{
base.Write();
Console.WriteLine("Name : {0}", this.Contact.Name);
}
}
public class CorporationBuilder : OrganizationBuilder
{
public CorporationBuilder(Corporation contact) : base(contact) { }
public virtual CorporationBuilder Date(DateTime date)
{
// Cast is required, but need this.Contact to be typeof 'C'
(this.Contact as Corporation).Date = date;
return this;
}
public override void Write()
{
base.Write();
Console.WriteLine("Date : {0}", (this.Contact as Corporation).Date.ToShortDateString());
}
}
/* Factory */
public class Factory
{
public static OrganizationBuilder Organization()
{
return new OrganizationBuilder(new Organization());
}
public static CorporationBuilder Corporation()
{
return new CorporationBuilder(new Corporation());
}
}
}
EDIT/UPDATE
Here's my first attempt at a solution (see below), although I'm stuck inside the Factory and not sure how to configure the .Organization() and .Corporation() method types.
namespace MyCompany
{
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Environment.NewLine);
Factory.Organization()
.ID(33)
.Name("Oranization A")
.Write();
Console.WriteLine("\n----------------------------\n");
Factory.Corporation()
.ID(44)
.Name("Company B")
.Date(DateTime.Today)
.Write();
Console.ReadLine();
}
}
/* Business Classes */
public abstract class Contact
{
public int ID { get; set; }
}
public class Organization : Contact
{
public string Name { get; set; }
}
public class Corporation : Organization
{
public DateTime Date { get; set; }
}
/* Builder */
public abstract class ContactBuilder<TContact, TBuilder>
where TContact : Contact
where TBuilder : ContactBuilder<TContact, TBuilder>
{
public ContactBuilder(TContact contact)
{
this.contact = contact;
}
private TContact contact;
public TContact Contact
{
get
{
return this.contact;
}
}
public virtual TBuilder ID(int id)
{
this.Contact.ID = id;
return this as TBuilder;
}
public virtual void Write()
{
Console.WriteLine("ID : {0}", this.Contact.ID);
}
}
public class OrganizationBuilder<TOrganization, TBuilder> : ContactBuilder<TOrganization, TBuilder> where TOrganization : Organization where TBuilder : OrganizationBuilder<TOrganization, TBuilder>
{
public OrganizationBuilder(TOrganization contact) : base(contact) { }
public virtual TBuilder Name(string name)
{
this.Contact.Name = name;
return this as TBuilder;
}
public override void Write()
{
base.Write();
Console.WriteLine("Name : {0}", this.Contact.Name);
}
}
public class CorporationBuilder<TCorporation, TBuilder> : OrganizationBuilder<TCorporation, TBuilder> where TCorporation : Corporation where TBuilder : CorporationBuilder<TCorporation, TBuilder>
{
public CorporationBuilder(TCorporation contact) : base(contact) { }
public virtual TBuilder Date(DateTime date)
{
this.Contact.Date = date;
return this as TBuilder;
}
public override void Write()
{
base.Write();
Console.WriteLine("Date : {0}", this.Contact.Date.ToShortDateString());
}
}
/* Factory */
public class Factory
{
public static OrganizationBuilder<Organization, OrganizationBuilder> Organization()
{
return new OrganizationBuilder<Organization, OrganizationBuilder>(new Organization());
}
public static CorporationBuilder<Corporation, CorporationBuilder> Corporation()
{
return new CorporationBuilder<Corporation, CorporationBuilder>(new Corporation());
}
}
}
Here's the specific problem area:
/* Factory */
public class Factory
{
public static OrganizationBuilder<Organization, OrganizationBuilder> Organization()
{
return new OrganizationBuilder<Organization, OrganizationBuilder>(new Organization());
}
public static CorporationBuilder<Corporation, CorporationBuilder> Corporation()
{
return new CorporationBuilder<Corporation, CorporationBuilder>(new Corporation());
}
}
How to configure the OrganizationBuilder and CorportationBuilder?