コード例 #1
0
        private Field AddProperty(TypeBuilder builder, FieldStateAllocator fieldStateAllocator, string name, Type type)
        {
            var fieldBuilder    = builder.DefineField($"_{name}", type, FieldAttributes.Private);
            var propertyBuilder = builder.DefineProperty(name, PropertyAttributes.None, type, null);

            var fieldState = fieldStateAllocator.Allocate();

            const MethodAttributes propertyMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;

            var getterBuilder = builder.DefineMethod($"get_{name}", propertyMethodAttributes, type, Type.EmptyTypes);
            var getterIL      = getterBuilder.GetILGenerator();

            getterIL.Emit(OpCodes.Ldarg_0);
            getterIL.Emit(OpCodes.Ldfld, fieldBuilder);
            getterIL.Emit(OpCodes.Ret);
            propertyBuilder.SetGetMethod(getterBuilder);

            var setterBuilder = builder.DefineMethod($"set_{name}", propertyMethodAttributes, null, new [] { type });
            var setterIL      = setterBuilder.GetILGenerator();

            setterIL.Emit(OpCodes.Ldarg_0);
            setterIL.Emit(OpCodes.Ldarg_1);
            setterIL.Emit(OpCodes.Stfld, fieldBuilder);
            fieldState.MarkAsUsed(setterIL);
            setterIL.Emit(OpCodes.Ret);
            propertyBuilder.SetSetMethod(setterBuilder);

            return(new Field(fieldBuilder, propertyBuilder, fieldState));
        }
コード例 #2
0
        public Type CreateTypeForProperties(IReadOnlyDictionary <string, Type> properties, IReadOnlyCollection <Type> interfaces)
        {
            var typeBuilder = _moduleBuilder.DefineUniqueType("ModelProperties");

            EnsureKeysAreCaseInsensitiveUnique(properties);

            foreach (var iface in interfaces)
            {
                properties = ImplementPropertiesInterface(typeBuilder, iface, properties);
            }

            var fieldStateAllocator = new FieldStateAllocator(typeBuilder);
            var fieldInfos          = new Dictionary <string, Field>();

            foreach (var property in properties)
            {
                var field = AddProperty(typeBuilder, fieldStateAllocator, property.Key, property.Value);
                fieldInfos.Add(property.Key, field);
            }

            var constructor = typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

            typeBuilder.AddInterfaceImplementation(typeof(IProperties <string, object>));

            ImplementGetEnumerator(typeBuilder, fieldStateAllocator, fieldInfos);
            ImplementTryGetValue(typeBuilder, fieldInfos);
            ImplementSet(typeBuilder, fieldInfos);
            ImplementCopy(typeBuilder, fieldStateAllocator, constructor, fieldInfos);

            return(typeBuilder.CreateTypeInfo());
        }
コード例 #3
0
        private void ImplementGetEnumerator(TypeBuilder typeBuilder, FieldStateAllocator fieldStateAllocator, IReadOnlyDictionary <string, Field> fieldInfos)
        {
            var enumeratorTypeGenerator = new ModelPropertyEnumeratorTypeGenerator(_moduleBuilder);
            // TODO _fieldState
            var constructor = enumeratorTypeGenerator.CreateEnumeratorType(typeBuilder, fieldStateAllocator.Fields, fieldInfos);

            MethodBuilder getEnumerator;
            {
                var methodBuilder = typeBuilder.DefineMethod(
                    "GetEnumerator",
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual,
                    typeof(IEnumerator <KeyValuePair <string, object> >),
                    new Type[0]);

                var il = methodBuilder.GetILGenerator();

                // return new ModelPropertyEnumerator(this, ...fieldState{i});
                il.Emit(OpCodes.Ldarg_0);
                for (var i = 0; i < fieldStateAllocator.Fields.Count; i++)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, fieldStateAllocator.Fields[i]);
                }
                il.Emit(OpCodes.Newobj, constructor);
                il.Emit(OpCodes.Ret);

                getEnumerator = methodBuilder;
            }

            {
                var methodBuilder = typeBuilder.DefineMethod(
                    "GetEnumerator",
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual,
                    typeof(IEnumerator),
                    new Type[0]);

                var il = methodBuilder.GetILGenerator();

                // return this.GetEnumerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, getEnumerator);
                il.Emit(OpCodes.Ret);
            }
        }
コード例 #4
0
        private static void ImplementCopy(TypeBuilder typeBuilder, FieldStateAllocator fieldStateAllocator, ConstructorInfo constructor, IReadOnlyDictionary <string, Field> fieldInfos)
        {
            var methodBuilder = typeBuilder.DefineMethod(
                "Copy",
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Final,
                typeof(IProperties <string, object>),
                new Type[0]);

            var il = methodBuilder.GetILGenerator();

            // var clonedProps = new ModelProperties();
            il.Emit(OpCodes.Newobj, constructor);
            var clonedProps = il.DeclareLocal(typeBuilder);

            il.Emit(OpCodes.Stloc, clonedProps);

            foreach (var field in fieldStateAllocator.Fields)
            {
                // clonedProps._fieldState = this._fieldState
                il.Emit(OpCodes.Ldloc, clonedProps);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, field);
                il.Emit(OpCodes.Stfld, field);
            }

            foreach (var pair in fieldInfos)
            {
                // clonedProps._key = this._key
                il.Emit(OpCodes.Ldloc, clonedProps);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, pair.Value.Builder);
                il.Emit(OpCodes.Stfld, pair.Value.Builder);
            }

            // return clonedProps;
            il.Emit(OpCodes.Ldloc, clonedProps);
            il.Emit(OpCodes.Ret);
        }