Ejemplo n.º 1
0
    /// <summary>
    /// Weaves an implementation of a property against the provided type.
    /// </summary>
    /// <param name="emitter">The emitter.</param>
    /// <param name="field">The attribute field.</param>
    /// <param name="property">The property.</param>
    /// <param name="interfaceType">The type of the interface.</param>
    public void WeaveImplementedProperty(TypeEmitter emitter, Variable field, PropertyDefinition property, TypeDefinition interfaceType)
    {
        var emitted     = emitter.EmitProperty(property.Name, property.PropertyType.Import(), toBackingField: true);
        var implemented = field.Type.GetProperty(property.Name, property.PropertyType)?.Resolve();

        if (implemented == null)
        {
            implemented = field.Type.GetProperty($"{interfaceType.FullName}.{property.Name}", returnType: property.PropertyType)?.Resolve();

            if (implemented == null)
            {
                throw new MissingMemberException($"Cannot implement '{field.Type.FullName}' as it does not implement property '{property.Name}'");
            }
        }

        var source = new PropertyEmitter(emitter, implemented);

        if (source.HasGetter && !emitted.HasGetter)
        {
            var getter      = emitted.GetGetter();
            var il          = getter.GetIL();
            var propertyGet = property.GetMethod?.Import() ?? implemented.GetMethod.Import();

            getter.Body.SimplifyMacros();

            il.Emit(Codes.Nop);
            il.Emit(Codes.ThisIf(field));
            il.Emit(Codes.Cast(interfaceType));
            il.Emit(Codes.Load(field));
            il.Emit(Codes.Invoke(propertyGet.GetGeneric()));
            il.Emit(Codes.Return);

            getter.Body.OptimizeMacros();
            getter.Body.InitLocals = true;
        }

        if (source.HasSetter && !emitted.HasSetter)
        {
            var setter      = emitted.GetSetter();
            var il          = setter.GetIL();
            var propertySet = property.SetMethod?.Import() ?? implemented.SetMethod.Import();

            setter.Body.SimplifyMacros();

            il.Emit(Codes.Nop);
            il.Emit(Codes.ThisIf(field));
            il.Emit(Codes.Load(field));
            il.Emit(Codes.Arg(setter.Target.IsStatic ? 0 : 1));
            il.Emit(Codes.Invoke(propertySet.GetGeneric()));
            il.Emit(Codes.Return);

            setter.Body.OptimizeMacros();
            setter.Body.InitLocals = true;
        }
    }