Exemplo n.º 1
0
        public void BuildTraveller()
        {
            if (_classBuilder.IsSealed)
            {
                throw new InvalidOperationException("Classification builder is sealed");
            }
            var target          = _typeProvider.GetOrCreate(_type);
            var members         = _dtContext.Members;
            var factoryArgument = new ILArgPointer(members.VisitArgsFactoryType, 1);


            var childTravellers = new Dictionary <Type, ChildTravellerInfo>();
            var argFields       = new Dictionary <SerializableProperty, FieldInfo>();

            var il             = _constructorBuilder.IL;
            var travellerIndex = 0;

            foreach (var property in target.Properties)
            {
                var argField      = _classBuilder.DefinePrivateField("_arg" + property.Ref.Name, members.VisitArgsType);
                var visitArgsCode = new ILCallMethodSnippet(factoryArgument, members.ConstructVisitArgsMethod, property.Ref.Name);
                il.Set(ILPointer.This(), argField, visitArgsCode);
                argFields.Add(property, argField);

                if (!ReflectionAnalyzer.TryGetComplexTypes(property.Ext, out var types))
                {
                    continue;
                }

                foreach (var type in types)
                {
                    if (childTravellers.ContainsKey(type))
                    {
                        continue;
                    }

                    var dynamicTraveller = _dtContext.Get(type);
                    var interfaceType    = typeof(IGraphTraveller <>).MakeGenericType(type);
                    var fieldBuilder     = _classBuilder.DefinePrivateField(string.Concat("_traveller", type.Name, ++travellerIndex), interfaceType);
                    childTravellers.Add(type, new ChildTravellerInfo {
                        Field             = fieldBuilder,
                        TravelWriteMethod = dynamicTraveller.TravelWriteMethod,
                        TravelReadMethod  = dynamicTraveller.TravelReadMethod
                    });

                    var getFactoryCode = ILSnippet.Call(factoryArgument, members.ConstructVisitArgsWithTypeMethod, type);
                    var newTraveller   = ILPointer.New(dynamicTraveller.Constructor, getFactoryCode);
                    il.Set(ILPointer.This(), fieldBuilder, newTraveller);
                }
            }
            il.Emit(OpCodes.Ret);

            var context = new TravellerContext(childTravellers, argFields);

            BuildWriteMethods(target, context);
            BuildReadMethods(target, context);

            _classBuilder.Seal();
            DynamicTraveller.Complete(_classBuilder.Type);
        }
Exemplo n.º 2
0
        public void CreateTestClassInstance()
        {
            var mt       = new DynamicMethod("Test$" + Guid.NewGuid(), typeof(string), Type.EmptyTypes);
            var il       = mt.GetILGenerator();
            var instance = ILPointer.New(EmitTestClass.ConstructorInfo, "Hello World");
            var property = ILPointer.Property(instance, typeof(IEmitTest).GetProperty("Message"));

            il.Load(property);
            il.Emit(OpCodes.Ret);
            var m = (Func <string>)mt.CreateDelegate(typeof(Func <string>));

            Assert.Equal("Hello World", m.Invoke());
        }
        private ILPointer GenerateCollectionContent(ExtendedType target, string refName)
        {
            var collectionMembers = new CollectionMembers(target);
            var isValueType       = collectionMembers.ElementType.GetTypeInfo().IsValueType;

            var collectionLocal = _il.NewLocal(collectionMembers.VariableType);
            var collection      = ILPointer.New(collectionMembers.Constructor)
                                  .Cast(collectionMembers.VariableType);

            _il.Set(collectionLocal, collection);

            var valueLocal = DeclareCollectionItemLocal(collectionMembers.ElementType);;

            if (collectionMembers.ElementTypeExt.IsValueOrNullableOfValue())
            {
                _il.WhileLoop(il => { // While condition
                    _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[collectionMembers.ElementType], Members.VisitArgsCollectionItem, valueLocal);

                    var valueNotFoundLabel = _il.NewLabel();
                    valueNotFoundLabel.TransferLongIfFalse();

                    if (isValueType)
                    {
                        _il.InvokeMethod(valueLocal, Members.Nullable[collectionMembers.ElementType].GetHasValue);
                    }
                    else
                    {
                        _il.AreEqual(valueLocal, ILPointer.Null);
                        _il.Negate();
                    }

                    var isNullLabel = _il.NewLabel();
                    isNullLabel.TransferLong();

                    valueNotFoundLabel.Mark();
                    _il.Load(0);
                    isNullLabel.Mark();
                }, il => {
                    _il.Load(collectionLocal);

                    GenerateLoadParamValueCode(valueLocal);

                    _il.EmitCall(OpCodes.Callvirt, collectionMembers.Add, null);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Dictionary)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateDictionaryEnumerateCode(collectionMembers.ElementType, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Collection)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateCollectionContent(collectionMembers.ElementTypeExt, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else
            {
                _il.WhileLoop(il => {
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionItem);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    GenerateCreateAndChildCallCode(valueLocal);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionItem);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, valueLocal);
                });
            }
            if (target.Ref.IsArray)
            {
                return(new ILCallMethodSnippet(collectionMembers.ToArray, collectionLocal));
            }

            return(collectionLocal);
        }