Ejemplo n.º 1
0
        void GenerateApartFieldsProperties(IILDynamicType classImpl, Type interfaceType)
        {
            var apartFields       = new Dictionary <string, IILField>();
            var initializedFields = new Dictionary <string, IILField>();
            var methods           = RelationInfo.GetMethods(interfaceType);
            var properties        = RelationInfo.GetProperties(interfaceType).ToArray();

            foreach (var method in methods)
            {
                var name = method.Name;
                if (!name.StartsWith("get_") && !name.StartsWith("set_"))
                {
                    continue;
                }

                IILField field;
                IILField initCheckField;
                var      propName = RelationInfo.GetPersistentName(method.Name.Substring(4), properties);

                if (!_relationInfo.ApartFields.ContainsKey(propName))
                {
                    throw new BTDBException($"Invalid property name {propName}.");
                }

                if (!apartFields.TryGetValue(propName, out field))
                {
                    field = classImpl.DefineField("_" + propName, method.ReturnType, FieldAttributes.Private);
                    apartFields[propName]       = field;
                    initCheckField              = classImpl.DefineField("_initialized_" + propName, typeof(bool), FieldAttributes.Private);
                    initializedFields[propName] = initCheckField;
                }
                else
                {
                    initCheckField = initializedFields[propName];
                }

                var reqMethod = classImpl.DefineMethod(method.Name, method.ReturnType,
                                                       method.GetParameters().Select(pi => pi.ParameterType).ToArray(),
                                                       MethodAttributes.Virtual | MethodAttributes.Public);
                if (name.StartsWith("set_"))
                {
                    reqMethod.Generator.Ldarg(0).Ldarg(1).Stfld(field)
                    .Ldarg(0).LdcI4(1).Stfld(initCheckField)
                    .Ret();
                }
                else
                {
                    var initializedLabel = reqMethod.Generator.DefineLabel("initialized");
                    reqMethod.Generator
                    .Ldarg(0).Ldfld(initCheckField)
                    .Brtrue(initializedLabel)
                    .Ldstr($"Cannot use uninitialized apart field {propName}")
                    .Newobj(() => new BTDBException(null))
                    .Throw()
                    .Mark(initializedLabel)
                    .Ldarg(0).Ldfld(field).Ret();
                }
                classImpl.DefineMethodOverride(reqMethod, method);
            }
        }