c# - Polymorphic object creation without IF condition -
i have abstract class this:
public abstract class records { public string type; public string source; public int value; protected records(string type, string source, int value) { type = type; source = source; value = value; } }
i create many classes inheriting class, , filling type field value coming static class this:
public static class contenttypesstring { public static string documentnew { { return "document - new month"; }} public static string headlinesnew { { return "headlines - new month"; }} etc... }
i able create child classes without having test "if foo == "document" type = contenttypesstring.documentnew
" or equivalent switch case (i have lot of cases)
is there design pattern suits needs?
edit : several people pointed out, should show how create instances.
private delegate splistitemcollection query(spweb web, datetime startdate, datetime enddate); private readonly query _queries; #region constructors public queryhandler(spweb web, datetime starttimeselecteddate, datetime endtimeselecteddate) { if (web == null) throw new argumentnullexception("web"); _web = web; _starttimeselecteddate = starttimeselecteddate; _endtimeselecteddate = endtimeselecteddate; recordslist = new list<records>(); // query invocation list _queries = numberpagepermonthquery.preparedquery; _queries += numberdocumentspermonthquery.preparedquery; _queries += numberheadlinespermonthquery.preparedquery; _queries += numberleaderboxpermonthquery.preparedquery; _queries += numbernewspermonthquery.preparedquery; _queries += numberpagesmodifiedpermonthquery.preparedquery; _queries += numberpicturespermonthquery.preparedquery; _queries += numberteasingpermonthquery.preparedquery; } #endregion constructors #region public methods // nullreferenceexception ? c#6 : item?.foreach(item => {}); ? /*** no c#6 compiler in vs2012... ***/ public void queries() { foreach (var del in _queries.getinvocationlist()) { var queryresult = (splistitemcollection) del.dynamicinvoke(_web, _starttimeselecteddate, _endtimeselecteddate); recordslist.add(new records(del.method.name, _web.title, queryresult.count)); } }
edit² : solution chose
public list<iquery> querylist { get; } // no delegate anymore, , static classes became implementations of iquery interface. #region constructors public queryhandler(spweb web, datetime starttimeselecteddate, datetime endtimeselecteddate) { if (web == null) throw new argumentnullexception("web"); _web = web; _starttimeselecteddate = starttimeselecteddate; _endtimeselecteddate = endtimeselecteddate; recordslist = new list<records>(); querylist = new list<iquery> { new numberdocumentspermonthquery(), new numberheadlinespermonthquery(), new numberleaderboxpermonthquery(), new numbernewspermonthquery(), new numberpagepermonthquery(), new numberpagesmodifiedpermonthquery(), new numberpicturespermonthquery(), new numberteasingpermonthquery() }; } #endregion constructors #region public methods // nullreferenceexception ? c#6 : item?.foreach(item => {}); ? /*** no c#6 compiler in vs2012... ***/ public void queries() { foreach (var query in querylist) { var queryresult = query.preparedquery(_web, _starttimeselecteddate, _endtimeselecteddate); recordslist.add(query.createrecord(_web.title, queryresult.count)); } }
record class follow implementation suggested @dbraillon implementation of iquery interface added method :
public records createrecord(string source, int value) { return new modifiedpagespermonthrecord(source, value); //or child of record class. }
and voilĂ . thank help.
you want make collection of records, string code of object type, , parameters.
one of many way - use builder.
firstly need configurate builder:
var builder = new recordbuilder() .registerbuilder("document", (source, value) => new document(source, value)) .registerbuilder("headlines", (source, value) => new headlines(source, value));
here specify how build record code "document" , "headlines".
to build record call:
builder.build("document", "source", 1);
builder code can (here if know how build record of passed type , make it):
public class recordbuilder { public records build(string code, string source, int value) { func<string, int, records> buildaction; if (recordbuilders.trygetvalue(code, out buildaction)) { return buildaction(source, value); } return null; } public recordbuilder registerbuilder(string code, func<string, int, records> buildaction) { recordbuilders.add(code, buildaction); return this; } private dictionary<string, func<string, int, records>> recordbuilders = new dictionary<string, func<string, int, records>> (); } public class document : records { public document(string source, int value) : base(contenttypesstring.documentnew, source, value) { } } public class headlines : records { public headlines(string source, int value) : base(contenttypesstring.headlinesnew, source, value) { } }
Comments
Post a Comment