public void CreateExplicitOverride_Generic()
        {
            var method = typeof(DomainType).GetMethod("GenericMethod");
            Func <MethodBodyCreationContext, Expression> bodyProvider = ctx => null;

            var fakeResult = CreateFakeGenericMethod();

            _methodFactoryMock
            .Setup(
                mock =>
                mock.CreateMethod(
                    _mutableType,
                    "Remotion.TypePipe.UnitTests.MutableReflection.Implementation.MemberFactory.MethodOverrideFactoryTest.DomainType.GenericMethod",
                    MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig,
                    It.IsAny <IEnumerable <GenericParameterDeclaration> >(),
                    It.IsAny <Func <GenericParameterContext, Type> >(),
                    It.IsAny <Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > >(),
                    bodyProvider))
            .Returns(fakeResult)
            .Callback(
                (
                    MutableType declaringType,
                    string nameArgument,
                    MethodAttributes attributes,
                    IEnumerable <GenericParameterDeclaration> genericParameters,
                    Func <GenericParameterContext, Type> returnTypeProvider,
                    Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > parameterProvider,
                    Func <MethodBodyCreationContext, Expression> bodyProviderArg) =>
            {
                var fakeGenericParameter    = ReflectionObjectMother.GetSomeType();
                var genericParameterContext = new GenericParameterContext(new[] { fakeGenericParameter });

                var returnType = returnTypeProvider(genericParameterContext);
                var parameters = parameterProvider(genericParameterContext).ToList();

                var genericParameter = genericParameters.Single();
                Assert.That(genericParameter.Name, Is.EqualTo("TPar"));
                Assert.That(genericParameter.Attributes, Is.EqualTo(GenericParameterAttributes.DefaultConstructorConstraint));
                Assert.That(
                    genericParameter.ConstraintProvider(genericParameterContext),
                    Is.EqualTo(new[] { typeof(DomainType), typeof(IDisposable) }));

                Assert.That(returnType, Is.SameAs(fakeGenericParameter));
                ParameterDeclarationTest.CheckParameter(parameters[0], typeof(int), "arg1", ParameterAttributes.None);
                ParameterDeclarationTest.CheckParameter(parameters[1], fakeGenericParameter, "arg2", ParameterAttributes.None);
            })
            .Verifiable();

            var result = _factory.CreateExplicitOverride(_mutableType, method, bodyProvider);

            _methodFactoryMock.Verify();
            Assert.That(result, Is.SameAs(fakeResult));
            Assert.That(result.AddedExplicitBaseDefinitions, Is.EqualTo(new[] { method }));
        }
        public void CreateExplicitOverride_Generic()
        {
            var method = typeof(DomainType).GetMethod("GenericMethod");
            Func <MethodBodyCreationContext, Expression> bodyProvider = ctx => null;

            var fakeResult = CreateFakeGenericMethod();

            _methodFactoryMock
            .Expect(
                mock =>
                mock.CreateMethod(
                    Arg.Is(_mutableType),
                    Arg.Is("Remotion.TypePipe.UnitTests.MutableReflection.Implementation.MemberFactory.MethodOverrideFactoryTest.DomainType.GenericMethod"),
                    Arg.Is(MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig),
                    Arg <IEnumerable <GenericParameterDeclaration> > .Is.Anything,
                    Arg <Func <GenericParameterContext, Type> > .Is.Anything,
                    Arg <Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > > .Is.Anything,
                    Arg.Is(bodyProvider)))
            .Return(fakeResult)
            .WhenCalled(
                mi =>
            {
                var fakeGenericParameter    = ReflectionObjectMother.GetSomeType();
                var genericParameterContext = new GenericParameterContext(new[] { fakeGenericParameter });

                var genericParameters = (IEnumerable <GenericParameterDeclaration>)mi.Arguments[3];
                var returnType        = ((Func <GenericParameterContext, Type>)mi.Arguments[4])(genericParameterContext);
                var parameters        = ((Func <GenericParameterContext, IEnumerable <ParameterDeclaration> >)mi.Arguments[5])(genericParameterContext).ToList();

                var genericParameter = genericParameters.Single();
                Assert.That(genericParameter.Name, Is.EqualTo("TPar"));
                Assert.That(genericParameter.Attributes, Is.EqualTo(GenericParameterAttributes.DefaultConstructorConstraint));
                Assert.That(genericParameter.ConstraintProvider(genericParameterContext), Is.EqualTo(new[] { typeof(DomainType), typeof(IDisposable) }));

                Assert.That(returnType, Is.SameAs(fakeGenericParameter));
                ParameterDeclarationTest.CheckParameter(parameters[0], typeof(int), "arg1", ParameterAttributes.None);
                ParameterDeclarationTest.CheckParameter(parameters[1], fakeGenericParameter, "arg2", ParameterAttributes.None);
            });

            var result = _factory.CreateExplicitOverride(_mutableType, method, bodyProvider);

            _methodFactoryMock.VerifyAllExpectations();
            Assert.That(result, Is.SameAs(fakeResult));
            Assert.That(result.AddedExplicitBaseDefinitions, Is.EqualTo(new[] { method }));
        }
        public void GetOrCreateOverride_BaseMethod_ImplicitOverride_Generic()
        {
            var baseDefinition = typeof(DomainType).GetMethod("GenericMethod");
            var inputMethod    = baseDefinition;
            var baseMethod     = baseDefinition;

            _relatedMethodFinderMock
            .Setup(mock => mock.GetOverride(baseDefinition, _mutableType.AddedMethods)).Returns((MutableMethodInfo)null).Verifiable();
            _relatedMethodFinderMock
            .Setup(mock => mock.GetMostDerivedOverride(baseDefinition, _mutableType.BaseType)).Returns(baseMethod).Verifiable();
            _relatedMethodFinderMock
            .Setup(
                mock => mock.IsShadowed(
                    baseDefinition,
                    It.Is <IEnumerable <MethodInfo> > (shadowingCandidates => shadowingCandidates.IsEquivalent(_mutableType.GetAllMethods()))))
            .Returns(false)
            .Verifiable();

            var fakeResult = CreateFakeGenericMethod();

            _methodFactoryMock
            .Setup(
                mock =>
                mock.CreateMethod(
                    _mutableType,
                    "GenericMethod",
                    MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot | MethodAttributes.HideBySig,
                    It.IsAny <IEnumerable <GenericParameterDeclaration> >(),
                    It.IsAny <Func <GenericParameterContext, Type> >(),
                    It.IsAny <Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > >(),
                    It.IsAny <Func <MethodBodyCreationContext, Expression> >()))
            .Returns(fakeResult)
            .Callback(
                (
                    MutableType declaringType,
                    string name,
                    MethodAttributes attributes,
                    IEnumerable <GenericParameterDeclaration> genericParameters,
                    Func <GenericParameterContext, Type> returnTypeProvider,
                    Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > parameterProvider,
                    Func <MethodBodyCreationContext, Expression> bodyProvider) =>
            {
                var fakeGenericParameter    = typeof(TypeThatCompliesWithConstraints);
                var genericParameterContext = new GenericParameterContext(new[] { fakeGenericParameter });

                var returnType = returnTypeProvider(genericParameterContext);
                var parameters = parameterProvider(genericParameterContext).ToList();

                var genericParameter = genericParameters.Single();
                Assert.That(genericParameter.Name, Is.EqualTo("TPar"));
                Assert.That(genericParameter.Attributes, Is.EqualTo(GenericParameterAttributes.DefaultConstructorConstraint));
                Assert.That(
                    genericParameter.ConstraintProvider(genericParameterContext),
                    Is.EqualTo(new[] { typeof(DomainType), typeof(IDisposable) }));

                Assert.That(returnType, Is.SameAs(fakeGenericParameter));
                ParameterDeclarationTest.CheckParameter(parameters[0], typeof(int), "arg1", ParameterAttributes.None);
                ParameterDeclarationTest.CheckParameter(parameters[1], fakeGenericParameter, "arg2", ParameterAttributes.None);

                var parameterExpressions = parameters.Select(p => p.Expression).ToList();
                var bodyContext          = new MethodBodyCreationContext(
                    _mutableType,
                    false,
                    parameterExpressions,
                    new[] { fakeGenericParameter },
                    returnType,
                    baseMethod);
                var body = bodyProvider(bodyContext);

                var expectedBody = Expression.Call(
                    bodyContext.This,
                    baseMethod.MakeTypePipeGenericMethod(fakeGenericParameter),
                    parameterExpressions);
                ExpressionTreeComparer.CheckAreEqualTrees(expectedBody, body);
            })
            .Verifiable();

            var result = _factory.GetOrCreateOverride(_mutableType, inputMethod, out _isNewlyCreated);

            _relatedMethodFinderMock.Verify();
            _methodFactoryMock.Verify();
            Assert.That(result, Is.SameAs(fakeResult));
            Assert.That(_isNewlyCreated, Is.True);
        }
        public void GetOrCreateOverride_BaseMethod_ImplicitOverride_Generic()
        {
            var baseDefinition = typeof(DomainType).GetMethod("GenericMethod");
            var inputMethod    = baseDefinition;
            var baseMethod     = baseDefinition;

            _relatedMethodFinderMock.Expect(mock => mock.GetOverride(baseDefinition, _mutableType.AddedMethods)).Return(null);
            _relatedMethodFinderMock.Expect(mock => mock.GetMostDerivedOverride(baseDefinition, _mutableType.BaseType)).Return(baseMethod);
            _relatedMethodFinderMock
            .Expect(mock => mock.IsShadowed(Arg.Is(baseDefinition), Arg <IEnumerable <MethodInfo> > .List.Equivalent(_mutableType.GetAllMethods())))
            .Return(false);

            var fakeResult = CreateFakeGenericMethod();

            _methodFactoryMock
            .Expect(
                mock =>
                mock.CreateMethod(
                    Arg.Is(_mutableType),
                    Arg.Is("GenericMethod"),
                    Arg.Is(MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot | MethodAttributes.HideBySig),
                    Arg <IEnumerable <GenericParameterDeclaration> > .Is.Anything,
                    Arg <Func <GenericParameterContext, Type> > .Is.Anything,
                    Arg <Func <GenericParameterContext, IEnumerable <ParameterDeclaration> > > .Is.Anything,
                    Arg <Func <MethodBodyCreationContext, Expression> > .Is.Anything))
            .Return(fakeResult)
            .WhenCalled(
                mi =>
            {
                var fakeGenericParameter    = typeof(TypeThatCompliesWithConstraints);
                var genericParameterContext = new GenericParameterContext(new[] { fakeGenericParameter });

                var genericParameters = (IEnumerable <GenericParameterDeclaration>)mi.Arguments[3];
                var returnType        = ((Func <GenericParameterContext, Type>)mi.Arguments[4])(genericParameterContext);
                var parameters        = ((Func <GenericParameterContext, IEnumerable <ParameterDeclaration> >)mi.Arguments[5])(genericParameterContext).ToList();

                var genericParameter = genericParameters.Single();
                Assert.That(genericParameter.Name, Is.EqualTo("TPar"));
                Assert.That(genericParameter.Attributes, Is.EqualTo(GenericParameterAttributes.DefaultConstructorConstraint));
                Assert.That(genericParameter.ConstraintProvider(genericParameterContext), Is.EqualTo(new[] { typeof(DomainType), typeof(IDisposable) }));

                Assert.That(returnType, Is.SameAs(fakeGenericParameter));
                ParameterDeclarationTest.CheckParameter(parameters[0], typeof(int), "arg1", ParameterAttributes.None);
                ParameterDeclarationTest.CheckParameter(parameters[1], fakeGenericParameter, "arg2", ParameterAttributes.None);

                var parameterExpressions = parameters.Select(p => p.Expression).ToList();
                var bodyContext          = new MethodBodyCreationContext(
                    _mutableType, false, parameterExpressions, new[] { fakeGenericParameter }, returnType, baseMethod);
                var body = ((Func <MethodBodyCreationContext, Expression>)mi.Arguments[6])(bodyContext);

                var expectedBody = Expression.Call(
                    bodyContext.This, baseMethod.MakeTypePipeGenericMethod(fakeGenericParameter), parameterExpressions.Cast <Expression>());
                ExpressionTreeComparer.CheckAreEqualTrees(expectedBody, body);
            });

            var result = _factory.GetOrCreateOverride(_mutableType, inputMethod, out _isNewlyCreated);

            _relatedMethodFinderMock.VerifyAllExpectations();
            _methodFactoryMock.VerifyAllExpectations();
            Assert.That(result, Is.SameAs(fakeResult));
            Assert.That(_isNewlyCreated, Is.True);
        }