Tuesday, 15 February 2011

c# - How to make a subclass constructor based on a parent class instance? -



c# - How to make a subclass constructor based on a parent class instance? -

i have item , subclass advanceditem (all made of value-types if matters):

public item { public string a; public bool b; public char c; ...// 20 fields } public advanceditem : item { public string z; }

it's easy create item or advanceditem independently:

var item = new item { = "aa", b = true, c = 'c', ... }; var aitem = new advanceditem { = "aa", b = true, c = 'c', ..., z = "zz" };

now, i want turn item advanceditem providing string z separately. in order accomplish thinking of using constructor.

attempt a:

// annoying, not using inheritance of advanceditem:item // need edit whenever alter class item public advanceditem(item item, string z) { = item.a; b = item.b; ...;//many lines z = z; }

attempt b:

// utilize inheritance seems need constructor duplicate public item(item item) { = item.a; b = item.b; ...;//many lines } public advanceditem(item item, string z) : base(item) { z = z; }

is there way improve sec effort avoid writing many lines of x = item.x? maybe solution auto-clone or auto-duplicate class public item(item item) wrote in 1 line?

consider using automapper re-create properties between objects.

this allow following:

item = new item { = 3, b = 'a', .... }; advanceditem advanced= mapper.map<advanceditem>(a); string z = "hello world"; advanced.z = z;

update

if not want utilize automapper can utilize reflection or better, expressions. create code bit more complex

consider these 2 types:

class item { public int a, b, c; public string d, e, f; private int privateint; public item(int valueofprivatefield) { privateint = valueofprivatefield; } } class advanceditem : item { public string g; public advanceditem(int valueofprivatefield) : base(valueofprivatefield) { } }

we can define method creates field-wise re-create expression. since mention fields value types can re-create each field 1 1 other object:

private static void mapfields<t>(t target, t source) { type type = typeof (t); if (!mappers.containskey(type)) { //build look re-create fields source target; var targetparam = expression.parameter(typeof(object)); var targetcasted = expression.typeas(targetparam, typeof(t)); var sourceparam = expression.parameter(typeof(object)); var sourcecasted = expression.typeas(sourceparam, typeof(t)); var setters = new list<expression>(); //get non-readonly fields foreach (var fieldinfo in typeof(t).getfields(bindingflags.instance | bindingflags.nonpublic | bindingflags.public).where(f => !f.isinitonly)) { look targetfield = expression.field(targetcasted, fieldinfo); look sourcefield = expression.field(sourcecasted, fieldinfo); setters.add(expression.assign(targetfield, sourcefield)); } look block = expression.block(setters); var mapperfunction = expression.lambda<action<object, object>>(block, targetparam, sourceparam).compile(); mappers[type] = mapperfunction; } mappers[type](target, source); } private static readonly dictionary<type, action<object, object>> mappers = new dictionary<type, action<object, object>>();

this caches functions map fields source target object, , should have close same performance manually writing this.a = a, this.b = b etc.

calling method:

static void main(string[] args) { var item = new item(56) {a = 5, b = 6}; var advanced = new advanceditem(0); mapfields(advanced, item); int = advanced.a; //5 int b = advanced.b; //6; //note advanced.privateint == 56! }

please note code more complex , less reliable automapper , not recommended or ready production systems.

c# inheritance constructor clone base-class

No comments:

Post a Comment