/// <summary> /// Maps the damage unit passed to this class to the controller, so the damage type can be used. /// Note: Mapping performance enchancements (caching the get/set delegates) learned here: https://blogs.msmvps.com/jonskeet/2008/08/09/making-reflection-fly-and-exploring-delegates/ /// </summary> /// <param name="objType">The type this controller was initialized with.</param> /// <returns>The number of properties mapped in the unit.</returns> private int MapDamageUnit() { var objType = typeof(T); this.log.LogMessage($"DamageMapper: Mapping Model { objType.Name } to DamageUnit."); this.modelMapping = new List <ModelPropertyConfig <T> >(); // Get the properties, and add their information to our mapping. var modelProperties = objType.GetProperties(); foreach (var prop in modelProperties) { // Get the get/set methods on this property. MethodInfo propGetter = objType.GetMethod($"get_{ prop.Name }"); MethodInfo propSetter = objType.GetMethod($"set_{ prop.Name }"); // Build the property profile, and add it to the global mapping. var propertyProfile = new ModelPropertyConfig <T>() { PropertyName = prop.Name, GetterMethod = this.CreateGetter(propGetter), SetterMethod = this.CreateSetter(propSetter) }; this.log.LogMessage($"DamageMapper: Mapped { prop.Name }."); this.modelMapping.Add(propertyProfile); } return(this.modelMapping.Count); }
private void ConvertToModel() { _model = Activator.CreateInstance(_modelCfg.ClassType); String[] locMsgs = new String[] { "model element (id=" + _modelCfg.Id + ", class=" + _modelCfg.ClassType.FullName + ") and property (name=", null, ")" }; foreach (KeyValuePair <int, ModelPropertyConfig> kvp in _modelCfg.Properties) { ModelPropertyConfig propCfg = kvp.Value; Object propVal = null; if (_struct.Fields.ContainsKey(propCfg.FieldBit.Seq)) { MessageField fld = _struct.Fields[propCfg.FieldBit.Seq]; if (fld.BytesValue == null) { //propVal = null; } else if (propCfg.Tlv != null || !String.IsNullOrEmpty(propCfg.TlvTagName)) { locMsgs[1] = propCfg.PropertyInfo.Name; int tlvLength = 0; propVal = ParseTlv(propCfg.PropertyInfo.PropertyType, propCfg.Tlv, propCfg.TlvTagName, propCfg.TlvLengthBytes, propCfg.TlvClassType, fld.BytesValue, String.Join("", locMsgs), false, ref tlvLength); } else if (propCfg.BitContent != null) { propVal = ParseBitContent(propCfg, fld); } else if (propCfg.GetPropertyValueFunc != null) { propVal = propCfg.GetPropertyValueFunc.DynamicInvoke(fld.BytesValue); } else { fld.FracDigits = propCfg.FracDigits; propVal = propCfg.GetValueFromBytes.GetValue(fld, null); } } Object propVal2 = propVal; if (propVal2 != null) { propVal2 = Util.GetAssignableValue(propCfg.PropertyInfo.PropertyType, propVal); if (propVal2 == null) { throw new MessageParserException("Cannot convert " + propVal.GetType().FullName + " to " + propCfg.PropertyInfo.PropertyType.FullName + ". Failed to convert incoming message to model " + _modelCfg.ClassType.FullName + " at property " + propCfg.PropertyInfo.Name); } } propCfg.PropertyInfo.SetValue(_model, propVal2, null); } }
private Object ParseBitContent(ModelPropertyConfig cfg, MessageField fld) { return(ParseBitContent(cfg.BitContent, fld.BytesValue)); }
private void CompileFields() { String[] locMsgs = new String[] { "model element (id=" + (_modelCfg.Id == null?"":_modelCfg.Id) + ", class=" + (_modelCfg.ClassType == null?"":_modelCfg.ClassType.FullName) + ") and property (name=", null, ")" }; foreach (KeyValuePair <int, MessageFieldConfig> kvpFldCfg in _msgCfg.Fields) { MessageFieldConfig fldCfg = kvpFldCfg.Value; ModelPropertyConfig propCfg = _modelCfg.Properties.ContainsKey(fldCfg.Seq) ? _modelCfg.Properties[fldCfg.Seq] : null; MessageField fld = (MessageField)Activator.CreateInstance(fldCfg.FieldType); Object propVal = propCfg == null ? null : propCfg.PropertyInfo.GetValue(_model, null); byte[] fldVal = null; if (fldCfg.FieldType != typeof(NullMessageField) && fldCfg.FieldType != typeof(MessageBitMap)) { if (/*propCfg==null ||*/ propVal == null) { if (_reqMsg != null && fldCfg.FromRequest) { IDictionary <int, MessageField> fields = _reqMsg.ParsedMessage.Fields; fldVal = fields.ContainsKey(fldCfg.Seq) ? fields[fldCfg.Seq].BytesValue : null; } } else if (propCfg.Tlv != null || !String.IsNullOrEmpty(propCfg.TlvTagName)) { locMsgs[1] = propCfg.PropertyInfo.Name; fldVal = CompileTlv(propCfg.Tlv, propCfg.TlvTagName, propCfg.TlvLengthBytes, propVal, String.Join("", locMsgs)); } else if (propCfg.BitContent != null) { fldVal = CompileBitContent(propCfg.BitContent, propVal); } else if (fldCfg.GetFieldBytesFunc != null) { fldVal = (byte[])fldCfg.GetFieldBytesFunc.DynamicInvoke(propVal); } byte[] header = null; if (fldVal != null || (propVal != null && propCfg.SetValueFromProperty != null)) //propCfg != null ==> propVal != null { if (fldCfg.Length >= 0) { if (fldVal != null && fldVal.Length != fld.GetBytesLengthFromActualLength(fldCfg.Length)) { throw new MessageCompilerException( "Incompatible length of bytes between compiled bytes length " + "and the defined one in configuration. Check the config for model (class=" + _modelCfg.ClassType.FullName + ") and property (name=" + (propCfg != null ? propCfg.PropertyInfo.Name : "") + ") and also its mapped field in message (id=" + _msgCfg.Id + ")"); } fld.Length = fldCfg.Length; } if (propVal is NibbleList) { fld.IsOdd = ((NibbleList)propVal).IsOdd; } if (propCfg != null) { fld.FracDigits = propCfg.FracDigits; } fld.VarLength = (fldCfg.Length < 0); if (fldVal != null) { fld.SetValue(fldVal); } else //if (propVal != null /* && propCfg != null */ && propCfg.SetValueFromProperty != null) { try { Type paramType = propCfg.SetValueFromProperty.GetParameters()[0].ParameterType; propVal = Util.GetAssignableValue(paramType, propVal); propCfg.SetValueFromProperty.Invoke(fld, new Object[] { propVal }); } catch (Exception ex) { throw new MessageCompilerException( "Cannot convert a property value to the coresponding message field. " + "Check the config for model (class=" + _modelCfg.ClassType.FullName + ") and property (name=" + propCfg.PropertyInfo.Name + ") and also its mapped field in message (id=" + _msgCfg.Id + ")", ex); } } if (fldCfg.LengthHeader >= 0) //It must be fld.VarLength == true (See XmlConfigParser) { header = MessageUtility.IntToHex((ulong)fld.Length, fldCfg.LengthHeader); } CompiledMessageField cmf = new CompiledMessageField(); cmf.Header = header; cmf.Content = fld; _struct.AddField(fldCfg.Seq, cmf); } } else //field is NULL type or BitMap { CompiledMessageField cmf = new CompiledMessageField(); cmf.Header = null; fld.Length = fldCfg.Length; cmf.Content = fld; _struct.AddField(fldCfg.Seq, cmf); } } }