c# - Merge two objects in a similar way as to PHP's array_merge -
in php
it's common practice pass array options class, , merge array set array holds defaults.
something this.
class myobject { private static $defaults = array('value'=>10); private $settings; public function something(array $settings = array()) { $this->settings = array_merge(static::defaults,$settings); } }
you can in javascript using jquery or other libraries introduce merge
function. these scripts let take 2 javascript objects , merge them together. allowing use 1 defaults, , override defaults.
i've found pattern useful, because allows configure large set of defaults assign settings need.
is there anyway in c#
?
i write function uses reflection on public properties, thinking must have been done.
edit:
this question has been asked before on stack, not answered in way provides same simplicity can done in php , javascript.
i wasn't able find answer did wanted. wrote small method this. it'll take 2 objects of same time, , merge fields/properties assuming null
value represents unassigned field/property.
here usage example. create class hold options communications class, let communication class have defaults , initialize communication user settings.
an example settings class.
public class comsettings { public int? port; public string? address; public bool? keepalive; }
an example class uses settings in constructor.
public class comlibrary { private static comsettings _defaults = new comsettings { port = 80, address = "localhost" }; protected comsettings settings; public comlibrary(comsettings psettings) { this.settings = objectmerge<comsettings>(_defaults, psettings); } }
this let different classes use comsettings
each have different defaults. limitation field/properties have support null
assignments.
here's implementation of objectmerge
.
/// <summary> /// creates new object contains properties of 2 objects merged together. /// </summary> /// <typeparam name="t">the class type merge.</typeparam> /// <param name="pdefaults">instance of defaults object.</param> /// <param name="psettings">instance of settings object.</param> /// <returns>a new instance of t merged results.</returns> public static t objectmerge<t>(t pdefaults, t psettings, bool pmergefields = true, bool pmergeproperties = true) t : class, new() { t target = new t(); type type = typeof(t); list<memberinfo> infos = new list<memberinfo>(type.getmembers()); foreach (memberinfo info in infos) { // copy values either defaults or settings if (pmergefields && info.membertype == membertypes.field) { fieldinfo field = (fieldinfo)info; if (field.ispublic) { object value = field.getvalue(psettings); value = (value == null) ? field.getvalue(pdefaults) : value; field.setvalue(target, value); } } // copy values either defaults or settings if (pmergeproperties && info.membertype == membertypes.property) { propertyinfo prop = (propertyinfo)info; if (prop.canwrite && prop.canread) { object value = prop.getvalue(psettings, null); value = (value == null) ? prop.getvalue(pdefaults, null) : value; prop.setvalue(target, value, null); } } } return target; }
and here simple unit test.
/// <summary> ///this test class coreutilstest , intended ///to contain coreutilstest unit tests ///</summary> [testclass()] public class coreutilstest { /// <summary> /// class perform testing on. /// </summary> public class myclassa { public string param1; public string param2; public string param3; } /// <summary> /// class perform testing on. /// </summary> public class myclassb { private string _param1; public string param1 { { return _param1; } set { _param1 = value; } } private string _param2; public string param2 { { return _param2; } set { _param2 = value; } } private string _param3; public string param3 { { return _param3; } set { _param3 = value; } } } /// <summary> ///a test setproperties ///</summary> [testmethod()] public void merging_fields() { myclassa defaults = new myclassa { param1 = "defaults" }; myclassa settings = new myclassa { param2 = "settings" }; myclassa results = coreutils.objectmerge<myclassa>(defaults, settings); assert.areequal("defaults", results.param1); assert.areequal("settings", results.param2); assert.areequal(null, results.param3); } [testmethod()] public void merging_properties() { myclassb defaults = new myclassb { param1 = "defaults" }; myclassb settings = new myclassb { param2 = "settings" }; myclassb results = coreutils.objectmerge<myclassb>(defaults, settings); assert.areequal("defaults", results.param1); assert.areequal("settings", results.param2); assert.areequal(null, results.param3); } }
Comments
Post a Comment