Beispiel #1
0
 public MapStrategy(IRecord record)
 {
     if (record.ContainsOnlyPrimitives())
     {
         var loader = DictionaryLoad.DirectlyFromRecord();
         _mapMethod = BuildMappingMethod(
             from p in typeof(TReturn).GetProperties(ObjectToDictionary.BindingFlagsForDTO)
             let neoName = Config.DotnetToNeoPropNames(p.Name)
                           where p.CanWrite
                           select new PropertyMap {
             Loader = loader, Property = p, RecordKey = neoName
         });
     }
     else if (record.ContainsOnlySingleNode())
     {
         var nodeKey = record.Keys.First();
         var loader  = DictionaryLoad.FromEmbeddedNode(nodeKey);
         _mapMethod = BuildMappingMethod(
             from p in typeof(TReturn).GetProperties(ObjectToDictionary.BindingFlagsForDTO)
             let neoName = Config.DotnetToNeoPropNames(p.Name)
                           where p.CanWrite
                           select new PropertyMap {
             Loader = loader, Property = p, RecordKey = neoName
         });
     }
 }
Beispiel #2
0
            private Func <IRecord, TReturn> BuildMappingMethod(IEnumerable <PropertyMap> propertyMaps)
            {
                var emit = Emit <Func <IRecord, TReturn> > .NewDynamicMethod($"MapTo_{typeof(TReturn).Name}_{Guid.NewGuid().ToBase64Guid()}");

                var ret       = emit.DeclareLocal(typeof(TReturn));
                var v         = emit.DeclareLocal(typeof(object));
                var check     = emit.DeclareLocal(typeof(bool));
                var valueDict = emit.DeclareLocal(typeof(IReadOnlyDictionary <string, object>));

                emit.NewObject(typeof(TReturn));
                emit.StoreLocal(ret);

                int            labelCounter  = 0;
                DictionaryLoad currentLoader = null;

                foreach (var pm in propertyMaps)
                {
                    if (!ReferenceEquals(currentLoader, pm.Loader))
                    {
                        // valueDict = record.Values || ((INode)record["v"]).Properties || ...
                        currentLoader = pm.Loader;
                        currentLoader.EmitLoad(emit, valueDict);
                    }

                    // check = dict.TryGetValue(recordKey, out v)
                    // if (check)
                    //   ret.Property = (cast)v;
                    var lbl = emit.DefineLabel("lbl_" + labelCounter);
                    emit.LoadLocal(valueDict);
                    emit.LoadConstant(pm.RecordKey);
                    emit.LoadLocalAddress(v);
                    emit.CallVirtual(TryGetValue);
                    emit.AsShorthand().Ldc(0); // <-- Copied from looking at IL
                    emit.AsShorthand().Ceq();  // it seems to turn around the true val
                    emit.StoreLocal(check);    // and jump to the label
                    emit.LoadLocal(check);
                    emit.BranchIfTrue(lbl);

                    emit.LoadLocal(ret);
                    emit.LoadLocal(v);

                    if (pm.Property.PropertyType.GetTypeInfo().IsValueType)
                    {
                        emit.UnboxAny(pm.Property.PropertyType);
                    }
                    else
                    {
                        emit.CastClass(pm.Property.PropertyType);
                    }
                    emit.CallVirtual(pm.Property.SetMethod);
                    emit.MarkLabel(lbl);
                    labelCounter++;
                }

                emit.LoadLocal(ret);
                emit.Return();
                return(emit.CreateDelegate());
            }