c# - Calling generic extension method with constraints -
i have model class 2 properties of different types - sourcedata
, destinationdata
. these properties holds instances of similar classes (in different namespaces) need compare manually , display differences.
i create generic extension method issame
problem, write simply:
// sourcedata: x => ..., destinatindata: y => ... var nameissame = model.issame(x => x.name, y => y.name); var ageissame = model.issame(x => x.age, y => y.age); ...
i prepared sample scenario can't write method issame
called above. have specify type generic method call.
public interface isource { } public interface idestination { } public class sourceperson : isource { public string name { get; set; } public int age { get; set; } } public class destinationperson : idestination { public string name { get; set; } public int age { get; set; } } public abstract class detailviewmodel<tsource, tdestination> tsource : isource tdestination : idestination { public tsource sourcedata { get; set; } public tdestination destinationdata { get; set; } } public class persondetailviewmodel : detailviewmodel<sourceperson, destinationperson> { }
now have model class of type persondetailviewmodel
implements abstract class detailviewmodel<>
. thought following implementation of method extensionmethods.issame
should called giving instance of persondetailviewmodel
might recognized because of constraints.
public static class extensionmethods { public static bool issame<tmodel, tsource, tdestination, tvalue>(this tmodel model, func<tsource, tvalue> sourceproperty, func<tdestination, tvalue> destinationproperty) tmodel : detailviewmodel<tsource, tdestination> tsource : isource tdestination : idestination { if (model.sourcedata == null) { return (model.destinationdata == null); } if (model.destinationdata == null) return false; return equals(sourceproperty(model.sourcedata), destinationproperty(model.destinationdata)); } }
however when try call extension method have specify types though compiler should know all.
class program { static void main(string[] args) { var model = new persondetailviewmodel { sourcedata = new sourceperson { name = "karel gott", age = 72 }, destinationdata = new destinationperson { name = "karel engles", age = 72 } }; console.writeline(model); console.writeline(); //var nameissame = model.issame(x => x.name, y => y.name); // doesn't work :-( var nameissame = model.issame<persondetailviewmodel, sourceperson, destinationperson, string>(x => x.name, y => y.name); console.writeline("name same: " + nameissame); //var ageissame = model.issame(x => x.age, y => y.age); // doesn't work :-( var ageissame = model.issame<persondetailviewmodel, sourceperson, destinationperson, int>(x => x.age, y => y.age); console.writeline("age same: " + ageissame); console.writeline(); console.writeline("press key exit ..."); console.readkey(true); } }
notice all: please don't write me, should compare equality differently. used here method issame simplicity. method works , code inside should else. need call without explicitly defined types. in opinion compiler should know them constrains.
in scenario used classes persondetailviewmodel, sourceperson, destinationperson ... in application there plenty of classes this. tsource , tdestination doesnt have same code inside, , properties should have different names. imagine want compare properties in these classes:
public class sourcecompany : isource { public int companyid { get; set; } public string nametraderegister { get; set; } public string addressstreet { get; set; } public string town { get; set; } } public class destinationcompany : idestination { public int id { get; set; } public string name { get; set; } public string streetname { get; set; } public string city { get; set; } } var idissame = model.issame(x => companyid, y => y.id);
ok, found solution. extension method should avoid tmodel , instead can declare detailviewmodel.
public static class extensionmethods { public static bool issame<tsource, tdestination, tvalue>(this detailviewmodel<tsource, tdestination> model, func<tsource, tvalue> sourceproperty, func<tdestination, tvalue> destinationproperty) tsource : isource tdestination : idestination { if (model.sourcedata == null) { return (model.destinationdata == null); } if (model.destinationdata == null) return false; return equals(sourceproperty(model.sourcedata), destinationproperty(model.destinationdata)); } }
Comments
Post a Comment