Пример #1
0
    /// <summary>
    /// Create a singleton field used to store parameter information for the provided method.
    /// </summary>
    /// <param name="method">The method weaver.</param>
    /// <param name="param">The parameter.</param>
    /// <returns></returns>
    public Variable CreateParameterInfo(MethodEmitter method, ParameterReference param)
    {
        var parent = method.Parent.Target.IsNotPublic ? method.Parent : CreateTypeContainer(method.Parent.Target);
        var type   = method.Parent.Target;

        var id   = method.Target.GetHashString();
        var name = $"<{method.Target.Name}${id}${param.Index}>k__ParameterInfo";

        var existing = parent.GetField(name, Context.Finder.ParameterInfo, toStatic: true);

        if (existing != null)
        {
            return(existing);
        }

        var field = parent.EmitField(name, Context.Finder.ParameterInfo, toStatic: true, toPublic: true);

        var il = parent.GetStaticConstructor().GetIL();

        il.Emit(Codes.Nop);
        il.Emit(Codes.LoadToken(type.HasGenericParameters ? method.Target : method.Target.GetGeneric()));
        il.Emit(Codes.LoadToken(type.GetGeneric()));
        il.Emit(Codes.InvokeStatic(Context.Finder.MethodBaseGetMethodFromHandleAndType));
        il.Emit(Codes.Invoke(Context.Finder.MethodBaseGetParameters));
        il.Emit(Codes.Int(param.Index));
        il.Emit(Codes.LoadArray);
        il.Emit(Codes.Store(field));

        return(field);
    }
Пример #2
0
    /// <summary>
    /// Create a singleton field used to store property information for the provided property.
    /// </summary>
    /// <param name="property">The property weaver.</param>
    /// <returns></returns>
    public Variable CreatePropertyInfo(PropertyEmitter property)
    {
        var parent = property.Parent.Target.IsNotPublic ? property.Parent : CreateTypeContainer(property.Parent.Target);
        var type   = property.Parent.Target;
        var sta    = (property.Target.GetMethod ?? property.Target.SetMethod).IsStatic;
        var name   = $"<{property.Target.Name}>k__PropertyInfo";

        var existing = parent.GetField(name, Context.Finder.PropertyInfo, toStatic: true);

        if (existing != null)
        {
            return(existing);
        }

        var field = parent.EmitField(name, Context.Finder.PropertyInfo, toStatic: true, toPublic: true);
        var flags = BindingFlags.NonPublic | BindingFlags.Public | (sta ? BindingFlags.Static : BindingFlags.Instance);

        var il = parent.GetStaticConstructor().GetIL();

        il.Emit(Codes.Nop);
        il.Emit(Codes.LoadToken(type.GetGeneric()));
        il.Emit(Codes.InvokeStatic(Context.Finder.TypeGetTypeFromHandle));
        il.Emit(Codes.String(property.Target.Name));
        il.Emit(Codes.Int((int)flags));
        il.Emit(Codes.Invoke(Context.Finder.TypeGetProperty));
        il.Emit(Codes.Store(field));

        return(field);
    }
Пример #3
0
    /// <summary>
    /// Weaves the constructor interceptors for a provided type and interceptor information.
    /// </summary>
    /// <param name="weaver">The weaver.</param>
    /// <param name="item">The interceptors.</param>
    public void WeaveConstructorInterceptors(TypeEmitter weaver, ConstructorInterceptorInfo item)
    {
        var constructors = weaver.GetConstructors();

        foreach (var init in item.Initializers)
        {
            var parameters = init.Parameters;

            if (parameters.Any(p => !p.IsOptional))
            {
                throw new NotSupportedException($"Cannot use constructor injection against a method with non-optional parameters");
            }

            var after  = init.GetAttribute(Context.Finder.IInjectAfterInitializer);
            var before = init.GetAttribute(Context.Finder.IInjectBeforeInitializer);

            if (init.HasGenericParameters)
            {
                throw new NotSupportedException($"Cannot use constructor injection against a generic method");
            }

            foreach (var ctor in constructors)
            {
                var il = ctor.GetIL();
                var st = init.IsStatic;

                il.Body.SimplifyMacros();
                il.Insert   = CodeInsertion.Before;
                il.Position = before != null ? (il.GetConstructorBaseOrThis()?.Next ?? il.GetFirst()) : il.GetLast();

                if (!st)
                {
                    il.Emit(Codes.This);
                }

                var type   = ctor.Parent.Target.GetGeneric();
                var method = (MethodReference)init;

                if (type.IsGenericInstance)
                {
                    var generic = (GenericInstanceType)type;
                    method = init.MakeGeneric(generic.GenericArguments.ToArray());
                }

                foreach (var param in parameters)
                {
                    il.Emit(Codes.Load(param.Constant));
                }

                il.Emit(st ? Codes.InvokeStatic(method) : Codes.Invoke(method));

                if (method.IsReturn())
                {
                    il.Emit(Codes.Pop);
                }

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

            if (after != null)
            {
                init.CustomAttributes.Remove(after);
            }

            if (before != null)
            {
                init.CustomAttributes.Remove(before);
            }
        }
    }