/// <inheritdoc cref="IDependencyEmitter" />
        public FieldBuilder CreateInterceptorDependency(TypeBuilder type)
        {
            Ensures.NotNull(type, nameof(type));

            var field = type.DefineField(
                "_interceptor",
                typeof(IInterceptor),
                FieldAttributes.Private | FieldAttributes.InitOnly);

            return(field);
        }
        /// <inheritdoc cref="IMockBehavior{TMock}" />
        public ICallBehavior <TMock> That(Expression <Action <TMock> > mockedCall)
        {
            Ensures.NotNull(mockedCall, nameof(mockedCall));

            if (mockedCall.Body is MethodCallExpression methodCall)
            {
                return(new CallBehavior <TMock>(Arrangements, methodCall.Method, this));
            }

            throw new NotImplementedException();
        }
예제 #3
0
        /// <inheritdoc cref="IAssemblyEmitter" />
        public ITypeDecoratorEmitter EmitDecoratorType(string typeFullName)
        {
            Ensures.NotNull(typeFullName, nameof(typeFullName));

            var builder = Module.Value.DefineType(
                typeFullName,
                TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class);
            var emitter = CreateTypeDecoratorEmitter(builder);

            return(emitter);
        }
        /// <inheritdoc cref="IArrangement" />
        public bool CanApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.HasFeature <IReturnValue <T> >())
            {
                return(invocation.Signature == Signature);
            }

            return(false);
        }
        /// <inheritdoc cref="IArrangement" />
        public bool TryApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.Signature == Signature)
            {
                throw ExceptionFactory();
            }

            return(false);
        }
        /// <summary>
        /// Emits a call to the <see cref="IInterceptor.Intercept(IInvocation)"/> method.
        /// </summary>
        /// <param name="body"> The body of the dynamic method or property. </param>
        /// <param name="interceptorField"> The <see cref="IInterceptor"/> backing field. </param>
        /// <param name="invocationVariable"> The local <see cref="IInvocation"/> variable. </param>
        /// <remarks>
        /// Emits the following source code:
        ///
        /// <![CDATA[
        ///     _interceptor.Intercept(invocation);
        /// ]]>
        /// </remarks>
        public static void EmitInterceptCall(
            this ILGenerator body, FieldBuilder interceptorField, LocalBuilder invocationVariable)
        {
            Ensures.NotNull(interceptorField, nameof(interceptorField));
            Ensures.NotNull(invocationVariable, nameof(invocationVariable));

            body.Emit(OpCodes.Ldarg_0);
            body.Emit(OpCodes.Ldfld, interceptorField);
            body.Emit(OpCodes.Ldloc, invocationVariable.LocalIndex);
            body.Emit(OpCodes.Callvirt, Intercept.Value);
            body.Emit(OpCodes.Pop);
        }
        /// <inheritdoc cref="IArrangementCollection" />
        public bool TryApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            var wasOneArrangementApplied = false;

            foreach (var arrangement in Arrangements)
            {
                wasOneArrangementApplied |= arrangement.TryApplyTo(invocation);
            }
            return(wasOneArrangementApplied);
        }
        /// <inheritdoc cref="IDependencyEmitter" />
        public FieldBuilder CreateDecorateeDependency(TypeBuilder type, Type decorateeType)
        {
            Ensures.NotNull(type, nameof(type));
            Ensures.NotNull(decorateeType, nameof(decorateeType));

            var field = type.DefineField(
                "_decoratee",
                decorateeType,
                FieldAttributes.Private | FieldAttributes.InitOnly);

            return(field);
        }
예제 #9
0
        /// <summary>
        /// Emits code to return the <see cref="IReturnValue{T}.ReturnValue"/>.
        /// </summary>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="returnValueFeatureVariable"> The emitted local <see cref="IReturnValue{T}"/> variable. </param>
        /// <typeparam name="T"> The concrete type of the return value. </typeparam>
        /// <remarks>
        /// Emits the following source code:
        /// <![CDATA[
        ///     return returnValueFeature.ReturnValue;
        /// ]]>
        /// </remarks>
        public static void EmitReturnStatement <T>(
            this ILGenerator body,
            LocalBuilder returnValueFeatureVariable)
        {
            Ensures.NotNull(returnValueFeatureVariable, nameof(returnValueFeatureVariable));

            body.Emit(OpCodes.Ldloc, returnValueFeatureVariable.LocalIndex);
            var returnValueSignature = ReturnValueFeaturePropertyCache.GetOrAdd(typeof(T), GetReturnValue <T>());

            body.Emit(OpCodes.Callvirt, returnValueSignature);
            body.Emit(OpCodes.Ret);
        }
예제 #10
0
        /// <summary>
        /// Emits code to return the <see cref="IAsyncInvocation{T}.AsyncReturnValue"/>.
        /// </summary>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="asyncFeatureVariable"> The emitted local <see cref="IAsyncInvocation{T}"/> variable. </param>
        /// <typeparam name="T"> The concrete type of the <see cref="IAsyncInvocation"/> feature. </typeparam>
        /// <remarks>
        /// Emits the following source code:
        /// <![CDATA[
        ///     return asyncFeature.AsyncReturnValue;
        /// ]]>
        /// </remarks>
        public static void EmitAsyncReturnStatement <T>(
            this ILGenerator body,
            LocalBuilder asyncFeatureVariable)
            where T : IAsyncInvocation
        {
            Ensures.NotNull(asyncFeatureVariable, nameof(asyncFeatureVariable));

            body.Emit(OpCodes.Ldloc, asyncFeatureVariable.LocalIndex);
            var asyncReturnValueSignature = AsyncFeatureReturnValueCache.GetOrAdd(typeof(T), GetAsyncFeatureReturnValue <T>());

            body.Emit(OpCodes.Callvirt, asyncReturnValueSignature);
            body.Emit(OpCodes.Ret);
        }
        /// <inheritdoc cref="IDynamicProxyFactory" />
        public T CreateDecorator <T>(T decoratee, IInterceptor interceptor) where T : notnull
        {
            Ensures.NotNull(interceptor, nameof(interceptor));

            var signature = typeof(T);
            var decorator = CreateDecorator(signature, decoratee, interceptor);

            if (decorator is T typedDecorator)
            {
                return(typedDecorator);
            }

            throw new Exception($"Unable to create a decorator for interface {signature.Name}");
        }
        /// <summary>
        /// Emits code to create a new <see cref="PropertyInvocation"/> instance for the given feature.
        /// </summary>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="propertySignatureVariable"> The emitted local <see cref="PropertyInfo"/> variable. </param>
        /// <param name="propertyFeatureVariable"> The emitted local <see cref="PropertyInvocation"/> variable. </param>
        /// <remarks>
        /// Emits the following source code:
        /// <![CDATA[
        ///     propertyFeature = new PropertyInvocation(propertySignature);
        /// ]]>
        /// </remarks>
        public static void EmitNewPropertyFeature(
            this ILGenerator body,
            LocalBuilder propertySignatureVariable,
            LocalBuilder propertyFeatureVariable)
        {
            Ensures.NotNull(propertySignatureVariable, nameof(propertySignatureVariable));
            Ensures.NotNull(propertyFeatureVariable, nameof(propertyFeatureVariable));

            // propertySignature
            body.Emit(OpCodes.Ldloc, propertySignatureVariable.LocalIndex);

            // propertyFeature = new PropertyInvocation(...)
            body.Emit(OpCodes.Newobj, CreatePropertyInvocation.Value);
            body.Emit(OpCodes.Stloc, propertyFeatureVariable.LocalIndex);
        }
        /// <inheritdoc cref="IArrangement" />
        public bool CanApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.TryGetFeature <IParameterOut>(out var outParameterFeature))
            {
                if (invocation.Signature == Signature)
                {
                    return(outParameterFeature
                           .OutParameterCollection
                           .Any(p => p.Name == OutParameterName && p.Type == typeof(T)));
                }
            }

            return(false);
        }
        /// <summary>
        /// Emits a call to the <see cref="IInterceptor.Intercept(IInvocation)"/> method along with an if statement.
        /// </summary>
        /// <param name="body"> The body of the dynamic method or property. </param>
        /// <param name="interceptorField"> The <see cref="IInterceptor"/> backing field. </param>
        /// <param name="invocationVariable"> The local <see cref="IInvocation"/> variable. </param>
        /// <param name="elseLabel"> The label that defines the start of the "else" block. </param>
        /// <remarks>
        /// Emits the following source code:
        ///
        /// <![CDATA[
        ///     if(_interceptor.Intercept(invocation))
        /// ]]>
        /// </remarks>
        public static void EmitIfInterceptCall(
            this ILGenerator body,
            FieldBuilder interceptorField,
            LocalBuilder invocationVariable,
            out Label elseLabel)
        {
            Ensures.NotNull(interceptorField, nameof(interceptorField));
            Ensures.NotNull(invocationVariable, nameof(invocationVariable));

            body.Emit(OpCodes.Ldarg_0);
            body.Emit(OpCodes.Ldfld, interceptorField);
            body.Emit(OpCodes.Ldloc, invocationVariable.LocalIndex);
            body.Emit(OpCodes.Callvirt, Intercept.Value);
            elseLabel = body.DefineLabel();
            body.Emit(OpCodes.Brtrue_S, elseLabel);
        }
        /// <summary>
        /// Emits code to create a new parameter feature instance for the given feature.
        /// </summary>
        /// <typeparam name="T">
        /// <see cref="ParameterIn"/>, <see cref="ParameterRef"/> or <see cref="ParameterOut"/>.
        /// </typeparam>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="methodSignatureVariable"> The emitted local <see cref="MethodInfo"/> variable. </param>
        /// <param name="parameterSignatures"> The dynamic method's parameter signatures. </param>
        /// <param name="parameterFeatureVariable"> The emitted local parameter variable. </param>
        /// <remarks>
        /// Emits the following source code:
        ///
        /// <![CDATA[
        ///     parameterFeature = new ParameterIn/Ref(methodSignature, new[] { parameter1, ... parameterN });
        /// ]]>
        ///
        /// or
        ///
        /// <![CDATA[
        ///     parameterFeature = new ParameterOut(methodSignature);
        /// ]]>
        /// </remarks>
        public static void EmitNewParameterFeature <T>(
            this ILGenerator body,
            LocalBuilder methodSignatureVariable,
            ParameterInfo[] parameterSignatures,
            LocalBuilder parameterFeatureVariable)
        {
            Ensures.NotNull(methodSignatureVariable, nameof(methodSignatureVariable));
            Ensures.NotNull(parameterSignatures, nameof(parameterSignatures));
            Ensures.NotNull(parameterFeatureVariable, nameof(parameterFeatureVariable));

            // methodSignature
            body.Emit(OpCodes.Ldloc, methodSignatureVariable.LocalIndex);

            if (typeof(T) != typeof(ParameterOut))
            {
                // new[] { parameter1, ... parameterN }
                body.Emit(OpCodes.Ldc_I4, parameterSignatures.Length);
                body.Emit(OpCodes.Newarr, typeof(object));
                for (var i = 0; i < parameterSignatures.Length; ++i)
                {
                    body.Emit(OpCodes.Dup);
                    body.Emit(OpCodes.Ldc_I4, i);
                    body.Emit(OpCodes.Ldarg, parameterSignatures[i].Position + 1);

                    var type = parameterSignatures[i].ParameterType;
                    if (type.IsByRef)
                    {
                        type = type.GetElementType()
                               ?? throw new MethodInfoException(typeof(Type), nameof(Type.GetElementType));
                        body.Emit(OpCodes.Ldobj, type);
                    }

                    if (type.IsValueType)
                    {
                        body.Emit(OpCodes.Box, type);
                    }

                    body.Emit(OpCodes.Stelem_Ref);
                }
            }

            // parameterFeature = new ParameterIn/Ref/Out(...)
            var featureCtor = ParameterFeatureCache.GetOrAdd(typeof(T), _ => InitializeParameterFeature <T>());

            body.Emit(OpCodes.Newobj, featureCtor);
            body.Emit(OpCodes.Stloc, parameterFeatureVariable.LocalIndex);
        }
        /// <inheritdoc cref="IArrangement" />
        public bool TryApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.Signature == Signature)
            {
                if (invocation.HasFeature <IAsyncInvocation>())
                {
                    if (invocation.TryGetFeature <IAsyncInvocation <T> >(out var asyncFeature))
                    {
                        asyncFeature.AsyncReturnValue = GetNextReturnValue();
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <Task <T> > >(out var asyncTaskFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncTaskFeature.AsyncReturnValue = Task.FromResult(returnValue);
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <ValueTask <T> > >(out var asyncValueTaskFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncValueTaskFeature.AsyncReturnValue = new ValueTask <T>(returnValue);
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <IAsyncEnumerable <T> > >(out var asyncEnumerableFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncEnumerableFeature.AsyncReturnValue = AsyncEnumerable.Create(_ =>
                                                                                         AsyncEnumerator.Create(
                                                                                             () => new ValueTask <bool>(true),
                                                                                             () => returnValue,
                                                                                             () => default));
                        return(true);
                    }
                }
                else if (invocation.TryGetFeature <IReturnValue <T> >(out var returnValueFeature))
                {
                    returnValueFeature.ReturnValue = GetNextReturnValue();
                    return(true);
                }
            }

            return(false);
        }
        /// <inheritdoc cref="IMockedDependencyFactory" />
        public IMockedDependency CreateMockedDependency(Type dependency, MockBehavior behavior)
        {
            Ensures.NotNull(dependency, nameof(dependency));
            Ensures.IsInterface(dependency);

            var arrangements         = new ArrangementCollection();
            var interceptor          = InterceptorFactory.CreateInterceptorFor(behavior, arrangements);
            var proxy                = DynamicProxyFactory.CreateForInterface(dependency, interceptor);
            var mockedDependencyType = typeof(MockedDependency <>).MakeGenericType(dependency);
            var instance             = Activator.CreateInstance(mockedDependencyType, new[] { arrangements, interceptor, proxy });

            if (instance is IMockedDependency mockedDependency)
            {
                return(mockedDependency);
            }

            throw new InvalidOperationException("Invalid mocked dependency instance");
        }
        /// <inheritdoc cref="IInterceptor" />
        public bool Intercept(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.TryGetFeature <IPropertySetterValue>(out var setter))
            {
                if (DiscoveredSetter == null)
                {
                    DiscoveredSetter = setter.Signature.GetSetMethod();
                    return(true);
                }
                else
                {
                    throw new Exception("Discovered more than one property setter call");
                }
            }

            return(false);
        }
        /// <inheritdoc cref="IMockBehavior{TMock}" />
        public ICallBehavior <TMock, TResult> That <TResult>(Expression <Func <TMock, TResult> > mockedCall)
        {
            Ensures.NotNull(mockedCall, nameof(mockedCall));

            if (mockedCall.Body is MethodCallExpression methodCall)
            {
                return(new CallBehavior <TMock, TResult>(Arrangements, methodCall.Method, this));
            }
            else if (mockedCall.Body is MemberExpression expression)
            {
                if (expression.Member is PropertyInfo signature && signature.CanRead)
                {
                    var getter = signature.GetGetMethod() ?? throw new Exception($"Property {signature.Name} has no getter");
                    return(new CallBehavior <TMock, TResult>(Arrangements, getter, this));
                }
            }

            throw new NotImplementedException();
        }
        /// <inheritdoc cref="IMockBehavior{TMock}" />
        public ICallBehavior <TMock> ThatAssigning(Action <TMock> mockedSetterCall)
        {
            Ensures.NotNull(mockedSetterCall, nameof(mockedSetterCall));

            var interceptor = new PropertySetterInterceptor();

            try
            {
                var proxy = ProxyFactory.Value.CreateForInterface <TMock>(interceptor);
                mockedSetterCall(proxy);
            }
            catch (Exception e)
            {
                throw new Exception("Action is no valid property setter", e);
            }

            var setter = interceptor.DiscoveredSetter ?? throw new Exception($"Property has no setter");

            return(new CallBehavior <TMock>(Arrangements, setter, this));
        }
        /// <inheritdoc cref="IInterceptorFactory" />
        public IInterceptor CreateInterceptorFor(MockBehavior behavior, IArrangementCollection arrangements)
        {
            Ensures.NotNull(arrangements);

            if (behavior == MockBehavior.Loose)
            {
                return(new LooseMockInterceptor(arrangements));
            }

            if (behavior == MockBehavior.Strict)
            {
                return(new StrictMockInterceptor(arrangements));
            }

            if (behavior == MockBehavior.Partial)
            {
                return(new PartialMockInterceptor(arrangements));
            }

            throw new NotSupportedException();
        }
        /// <summary>
        /// Emit a call to <see cref="IParameterRefOrOut.GetValue{T}(string)"/> and store the result in the
        /// associated ref or out parameter of the intercepted method.
        /// </summary>
        /// <typeparam name="T">
        /// <see cref="ParameterRef"/> or <see cref="ParameterOut"/>.
        /// </typeparam>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="parameterSignatures"> The signatures of the ref/out parameter to be synced. </param>
        /// <param name="parameterRefFeatureVariable"> The emitted local parameter ref/out feature variable. </param>
        /// <remarks>
        /// Emits the following source code:
        /// <![CDATA[
        ///     ref/outParameter1 = parameterRef/OutFeature.GetValue<ParameterType1>("ParameterName1");
        ///     ...
        ///     ref/outParameterN = parameterRef/OutFeature.GetValue<ParameterTypeN>("ParameterNameN");
        /// ]]>
        /// </remarks>
        public static void EmitSyncParameter <T>(
            this ILGenerator body,
            ParameterInfo[] parameterSignatures,
            LocalBuilder parameterRefFeatureVariable)
        {
            Ensures.NotNull(parameterSignatures, nameof(parameterSignatures));
            Ensures.NotNull(parameterRefFeatureVariable, nameof(parameterRefFeatureVariable));

            foreach (var parameterSignature in parameterSignatures)
            {
                body.Emit(OpCodes.Ldarg, parameterSignature.Position + 1);
                body.Emit(OpCodes.Ldloc, parameterRefFeatureVariable.LocalIndex);
                body.Emit(OpCodes.Ldstr, parameterSignature.Name ?? "unknown");

                var type = parameterSignature.ParameterType.GetElementType()
                           ?? throw new MethodInfoException(typeof(Type), nameof(Type.GetElementType));
                var getValue = ParameterGetValueCache.GetOrAdd(type, _ => InitializeParameterGetValue(type));
                body.Emit(OpCodes.Callvirt, getValue);
                body.Emit(OpCodes.Stobj, type);
            }
        }
        /// <inheritdoc cref="IArrangement" />
        public bool TryApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.Signature == Signature)
            {
                if (invocation.TryGetFeature <IParameterOut>(out var outParameterFeature))
                {
                    var parameter = outParameterFeature
                                    .OutParameterCollection
                                    .SingleOrDefault(p => p.Name == OutParameterName && p.Type == typeof(T));
                    if (parameter != null)
                    {
                        parameter.Value = OutParameterValue;
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <inheritdoc cref="IDynamicProxyFactory" />
        public object CreateForInterface(Type signature, IInterceptor interceptor)
        {
            Ensures.NotNull(signature, nameof(signature));
            Ensures.NotNull(interceptor, nameof(interceptor));

            try
            {
                var proxyType = ProxyTypeCache.GetOrAdd(signature, EmitProxyTypeFor);
                var proxy     = Activator.CreateInstance(proxyType, new[] { interceptor });
                if (proxy != null)
                {
                    return(proxy);
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Unable to create a proxy for interface {signature.Name}", e);
            }

            throw new Exception($"Unable to create a proxy for interface {signature.Name}");
        }
        /// <inheritdoc cref="IDynamicProxyFactory" />
        public object CreateDecorator(Type signature, object decoratee, IInterceptor interceptor)
        {
            Ensures.NotNull(signature, nameof(signature));
            Ensures.NotNull(decoratee, nameof(decoratee));
            Ensures.NotNull(interceptor, nameof(interceptor));

            try
            {
                var decoratorType = PartialProxyTypeCache.GetOrAdd(signature, EmitPartialProxyTypeFor);
                var decorator     = Activator.CreateInstance(decoratorType, new[] { decoratee, interceptor });
                if (decorator != null)
                {
                    return(decorator);
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Unable to create a decorator for interface {signature.Name}", e);
            }

            throw new Exception($"Unable to create a decorator for interface {signature.Name}");
        }
예제 #26
0
        /// <inheritdoc cref="ITypeEmitter" />
        public void ImplementInterface(Type signature)
        {
            Ensures.NotNull(signature);
            Ensures.IsInterface(signature);

            var interceptorField = Dependencies.CreateInterceptorDependency(Type);

            Dependencies.CreateConstructor(Type, interceptorField);
            Type.AddInterfaceImplementation(signature);

            foreach (var property in signature.GetProperties())
            {
                var emitter = PropertyEmitterFactory.CreatePropertyEmitterFor(property, Type, interceptorField);
                emitter.EmitPropertyImplementation();
            }

            foreach (var method in signature.GetMethods().Where(m => !m.IsSpecialName))
            {
                var emitter = MethodEmitterFactory.CreateMethodEmitterFor(method, Type, interceptorField);
                emitter.EmitMethodImplementation();
            }
        }
        /// <summary>
        /// Creates a new instance of the <see cref="ParameterIn"/> type.
        /// </summary>
        /// <param name="signature"> The intercepted method's signature. </param>
        /// <param name="values"> The intercepted method's in(put) parameters. </param>
        public ParameterIn(MethodInfo signature, object?[] values)
        {
            Ensures.NotNull(signature, nameof(signature));
            Ensures.NotNull(values, nameof(values));

            var inputParameter  = new List <Parameter>();
            var methodParameter = signature.GetParameters();

            for (var i = 0; i < values.Length; ++i)
            {
                var parameter = methodParameter[i];
                if (!parameter.IsOut && !parameter.ParameterType.IsByRef)
                {
                    var value = values[i];
                    inputParameter.Add(new Parameter(
                                           parameter.Name ?? "unknown",
                                           parameter.ParameterType,
                                           value));
                }
            }
            InputParameterCollection = inputParameter;
        }
        /// <summary>
        /// Emits code to create a new <see cref="Invocation"/> instance for the given method signature and features.
        /// </summary>
        /// <param name="body"> The body of the dynamic method. </param>
        /// <param name="invocationVariable"> The local <see cref="Invocation"/> variable. </param>
        /// <param name="methodSignatureVariable"> The emitted local <see cref="MethodInfo"/> variable. </param>
        /// <param name="invocationFeatureVariables"> A colleciton of local <see cref="IInvocationFeature"/> variables. </param>
        /// <remarks>
        /// Emits the following source code:
        /// <![CDATA[
        ///     invocation = new Invocation(methodSignature, feature1, feature2, ... featureN);
        /// ]]>
        /// </remarks>
        public static void EmitNewInvocation(
            this ILGenerator body,
            LocalBuilder invocationVariable,
            LocalBuilder methodSignatureVariable,
            IReadOnlyList <LocalBuilder> invocationFeatureVariables)
        {
            Ensures.NotNull(invocationVariable, nameof(invocationVariable));
            Ensures.NotNull(methodSignatureVariable, nameof(methodSignatureVariable));
            Ensures.NotNull(invocationFeatureVariables, nameof(invocationFeatureVariables));

            // methodSignature
            body.Emit(OpCodes.Ldloc, methodSignatureVariable.LocalIndex);

            if (invocationFeatureVariables == null || invocationFeatureVariables.Count == 0)
            {
                // Array.Empty<IInvocationFeature>()
                body.Emit(OpCodes.Call, ArrayEmptyInvocationFeature.Value);
            }
            else
            {
                // feature1, feature2, ... featurenN
                body.Emit(OpCodes.Ldc_I4, invocationFeatureVariables.Count);
                body.Emit(OpCodes.Newarr, typeof(IInvocationFeature));

                for (var i = 0; i < invocationFeatureVariables.Count; ++i)
                {
                    var feature = invocationFeatureVariables[i];

                    body.Emit(OpCodes.Dup);
                    body.Emit(OpCodes.Ldc_I4, i);
                    body.Emit(OpCodes.Ldloc, feature.LocalIndex);
                    body.Emit(OpCodes.Stelem_Ref);
                }
            }

            // invocation = new Invocation(...)
            body.Emit(OpCodes.Newobj, CreateInvocation.Value);
            body.Emit(OpCodes.Stloc, invocationVariable.LocalIndex);
        }
        /// <inheritdoc cref="ICompositionRoot" />
        public void Compose(IServiceRegistry serviceRegistry)
        {
            Ensures.NotNull(serviceRegistry, nameof(serviceRegistry));

            serviceRegistry.Register <IDynamicProxyFactory, DynamicProxyFactory>();
            serviceRegistry.Register <IAssemblyEmitter, AssemblyEmitter>();
            serviceRegistry.Register <IDependencyEmitter, DependencyEmitter>();
            serviceRegistry.Register <IMethodEmitterFactory, MethodEmitterFactory>();
            serviceRegistry.Register <IMethodDecoratorEmitterFactory, MethodDecoratorEmitterFactory>();
            serviceRegistry.Register <IPropertyEmitterFactory, PropertyEmitterFactory>();
            serviceRegistry.Register <IPropertyDecoratorEmitterFactory, PropertyDecoratorEmitterFactory>();
            serviceRegistry.Register <TypeBuilder, ITypeEmitter>((factory, typeBuilder) =>
            {
                var dependencyEmitter      = factory.GetInstance <IDependencyEmitter>();
                var methodEmitterFactory   = factory.GetInstance <IMethodEmitterFactory>();
                var propertyEmitterFactory = factory.GetInstance <IPropertyEmitterFactory>();
                return(new TypeEmitter(
                           typeBuilder,
                           dependencyEmitter,
                           methodEmitterFactory,
                           propertyEmitterFactory));
            });
            serviceRegistry.Register <TypeBuilder, ITypeDecoratorEmitter>((factory, typeBuilder) =>
            {
                var dependencyEmitter      = factory.GetInstance <IDependencyEmitter>();
                var methodEmitterFactory   = factory.GetInstance <IMethodDecoratorEmitterFactory>();
                var propertyEmitterFactory = factory.GetInstance <IPropertyDecoratorEmitterFactory>();
                return(new TypeDecoratorEmitter(
                           typeBuilder,
                           dependencyEmitter,
                           methodEmitterFactory,
                           propertyEmitterFactory));
            });
            serviceRegistry.Register <IInterceptorFactory, InterceptorFactory>();
            serviceRegistry.Register <IMockedDependencyFactory, MockedDependencyFactory>();
        }
예제 #30
0
        /// <summary>
        /// Creates a new instance of the <see cref="ParameterRef"/> type.
        /// </summary>
        /// <param name="signature"> The intercepted method's signature. </param>
        /// <param name="values"> The intercepted method's ref parameters. </param>
        public ParameterRef(MethodInfo signature, object?[] values)
        {
            Ensures.NotNull(signature, nameof(signature));
            Ensures.NotNull(values, nameof(values));

            var refParameter    = new List <Parameter>();
            var methodParameter = signature.GetParameters();

            for (var i = 0; i < methodParameter.Length; ++i)
            {
                var parameter = methodParameter[i];
                if (parameter.ParameterType.IsByRef)
                {
                    var value = values[i];
                    var type  = parameter.ParameterType.GetElementType()
                                ?? throw new MethodInfoException(typeof(Type), nameof(Type.GetElementType));
                    refParameter.Add(new Parameter(
                                         parameter.Name ?? "unknown",
                                         type,
                                         value));
                }
            }
            RefParameterCollection = refParameter;
        }