private void ImplementBaseCallForRequirement(RequiredMethodDefinition requiredMethod) { if (requiredMethod.ImplementingMethod.DeclaringClass == _targetClassDefinition) { ImplementBaseCallForRequirementOnTarget(requiredMethod); } else { ImplementBaseCallForRequirementOnMixin(requiredMethod); } }
public void BaseMethods() { TargetClassDefinition targetClass = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(BaseType3)); RequiredNextCallTypeDefinition req1 = targetClass.RequiredNextCallTypes[typeof(IBaseType31)]; Assert.That(req1.Methods.Count, Is.EqualTo(typeof(IBaseType31).GetMembers().Length)); RequiredMethodDefinition member1 = req1.Methods[typeof(IBaseType31).GetMethod("IfcMethod")]; Assert.That(member1.FullName, Is.EqualTo("Remotion.Mixins.UnitTests.Core.TestDomain.IBaseType31.IfcMethod")); Assert.That(member1.DeclaringRequirement, Is.SameAs(req1)); Assert.That(member1.Parent, Is.SameAs(req1)); Assert.That(member1.InterfaceMethod, Is.EqualTo(typeof(IBaseType31).GetMethod("IfcMethod"))); Assert.That(member1.ImplementingMethod, Is.EqualTo(targetClass.Methods[typeof(BaseType3).GetMethod("IfcMethod")])); RequiredNextCallTypeDefinition req2 = targetClass.RequiredNextCallTypes[typeof(IBT3Mixin4)]; Assert.That(req2.Methods.Count, Is.EqualTo(typeof(IBT3Mixin4).GetMembers().Length)); RequiredMethodDefinition member2 = req2.Methods[typeof(IBT3Mixin4).GetMethod("Foo")]; Assert.That(member2.FullName, Is.EqualTo("Remotion.Mixins.UnitTests.Core.TestDomain.IBT3Mixin4.Foo")); Assert.That(member2.DeclaringRequirement, Is.SameAs(req2)); Assert.That(member2.Parent, Is.SameAs(req2)); Assert.That(member2.InterfaceMethod, Is.EqualTo(typeof(IBT3Mixin4).GetMethod("Foo"))); Assert.That(member2.ImplementingMethod, Is.EqualTo(targetClass.Mixins[typeof(BT3Mixin4)].Methods[typeof(BT3Mixin4).GetMethod("Foo")])); using (MixinConfiguration.BuildFromActive().ForClass <BaseType3> ().Clear().AddMixins(typeof(BT3Mixin7Base), typeof(BT3Mixin4)).EnterScope()) { TargetClassDefinition targetClass2 = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(BaseType3)); RequiredNextCallTypeDefinition req3 = targetClass2.RequiredNextCallTypes[typeof(ICBaseType3BT3Mixin4)]; Assert.That(req3.Methods.Count, Is.EqualTo(0)); req3 = targetClass2.RequiredNextCallTypes[typeof(ICBaseType3)]; Assert.That(req3.Methods.Count, Is.EqualTo(0)); req3 = targetClass2.RequiredNextCallTypes[typeof(IBaseType31)]; Assert.That(req3.Methods.Count, Is.EqualTo(1)); req3 = targetClass2.RequiredNextCallTypes[typeof(IBT3Mixin4)]; Assert.That(req3.Methods.Count, Is.EqualTo(1)); RequiredMethodDefinition member3 = req3.Methods[typeof(IBT3Mixin4).GetMethod("Foo")]; Assert.That(member3, Is.Not.Null); Assert.That(member3.ImplementingMethod, Is.EqualTo(targetClass2.Mixins[typeof(BT3Mixin4)].Methods[typeof(BT3Mixin4).GetMethod("Foo")])); } }
// Required base call method implemented by extension -> either as an overridde or not // If an overridde, delegate to next in chain, else simply delegate to the extension implementing it field private void ImplementBaseCallForRequirementOnMixin(RequiredMethodDefinition requiredMethod) { var methodImplementation = _type.AddExplicitOverride(requiredMethod.InterfaceMethod, ctx => Expression.Default(ctx.ReturnType)); if (requiredMethod.ImplementingMethod.Base == null) // this is not an override, call method directly on extension { methodImplementation.SetBody(ctx => _nextCallMethodGenerator.CreateBaseCallToTarget(ctx, requiredMethod.ImplementingMethod)); } else // this is an override, go to next in chain { // a base call for this has already been implemented as an overriden method, but we explicitly implement the call chains anyway: it's // slightly easier and better for performance Assertion.IsTrue(_overriddenMethodToImplementationMap.ContainsKey(requiredMethod.ImplementingMethod.Base)); methodImplementation.SetBody(ctx => _nextCallMethodGenerator.CreateBaseCallToNextInChain(ctx, requiredMethod.ImplementingMethod.Base)); } }
// Required base call method implemented by "this" -> either overridden or not // If overridden, delegate to next in chain, else simply delegate to "this" field private void ImplementBaseCallForRequirementOnTarget(RequiredMethodDefinition requiredMethod) { var methodImplementation = _type.AddExplicitOverride(requiredMethod.InterfaceMethod, ctx => Expression.Default(ctx.ReturnType)); if (requiredMethod.ImplementingMethod.Overrides.Count == 0) // this is not an overridden method, call method directly on _this { methodImplementation.SetBody(ctx => _nextCallMethodGenerator.CreateBaseCallToTarget(ctx, requiredMethod.ImplementingMethod)); } else // this is an override, go to next in chain { // a base call for this might already have been implemented as an overriden method, but we explicitly implement the call chains anyway: it's // slightly easier and better for performance Assertion.IsFalse(_targetClassDefinition.Methods.ContainsKey(requiredMethod.InterfaceMethod)); methodImplementation.SetBody(ctx => _nextCallMethodGenerator.CreateBaseCallToNextInChain(ctx, requiredMethod.ImplementingMethod)); } }
private static void CheckRequiredMethods(RequirementDefinitionBase requirement, ClassDefinitionBase implementer, string memberPrefix) { BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; Assert.That(requirement.Methods.Count, Is.EqualTo(5)); RequiredMethodDefinition method = requirement.Methods[typeof(IMixinRequiringAllMembersRequirements).GetMethod("Method", bf)]; Assert.That(method, Is.Not.Null); Assert.That(method.InterfaceMethod, Is.EqualTo(typeof(IMixinRequiringAllMembersRequirements).GetMethod("Method", bf))); Assert.That(method.ImplementingMethod, Is.SameAs(implementer.Methods[implementer.Type.GetMethod(memberPrefix + "Method", bf)])); RequiredMethodDefinition propertyGetter = requirement.Methods[typeof(IMixinRequiringAllMembersRequirements).GetMethod("get_Property", bf)]; Assert.That(propertyGetter, Is.Not.Null); Assert.That(propertyGetter.InterfaceMethod, Is.EqualTo(typeof(IMixinRequiringAllMembersRequirements).GetMethod("get_Property", bf))); Assert.That(propertyGetter.ImplementingMethod, Is.SameAs(implementer.Properties[implementer.Type.GetProperty(memberPrefix + "Property", bf)].GetMethod)); RequiredMethodDefinition propertySetter = requirement.Methods[typeof(IMixinRequiringAllMembersRequirements).GetMethod("set_Property", bf)]; Assert.That(propertySetter, Is.Not.Null); Assert.That(propertySetter.InterfaceMethod, Is.EqualTo(typeof(IMixinRequiringAllMembersRequirements).GetMethod("set_Property", bf))); Assert.That(propertySetter.ImplementingMethod, Is.SameAs(implementer.Properties[implementer.Type.GetProperty(memberPrefix + "Property", bf)].SetMethod)); RequiredMethodDefinition eventAdder = requirement.Methods[typeof(IMixinRequiringAllMembersRequirements).GetMethod("add_Event", bf)]; Assert.That(eventAdder, Is.Not.Null); Assert.That(eventAdder.InterfaceMethod, Is.EqualTo(typeof(IMixinRequiringAllMembersRequirements).GetMethod("add_Event", bf))); Assert.That(eventAdder.ImplementingMethod, Is.SameAs(implementer.Events[implementer.Type.GetEvent(memberPrefix + "Event", bf)].AddMethod)); RequiredMethodDefinition eventRemover = requirement.Methods[typeof(IMixinRequiringAllMembersRequirements).GetMethod("remove_Event", bf)]; Assert.That(eventRemover, Is.Not.Null); Assert.That(eventRemover.InterfaceMethod, Is.EqualTo(typeof(IMixinRequiringAllMembersRequirements).GetMethod("remove_Event", bf))); Assert.That(eventRemover.ImplementingMethod, Is.SameAs(implementer.Events[implementer.Type.GetEvent(memberPrefix + "Event", bf)].RemoveMethod)); }
public void Visit(RequiredMethodDefinition requiredMethod) { ArgumentUtility.CheckNotNull("requiredMethod", requiredMethod); CheckRules(_requiredMethodRules, requiredMethod); }
private void ImplementRequiredDuckMethod(RequiredMethodDefinition requiredMethod) { _concreteTarget.AddExplicitOverride( requiredMethod.InterfaceMethod, ctx => Expression.Call(ctx.This, requiredMethod.ImplementingMethod.MethodInfo, ctx.Parameters.Cast <Expression>())); }
public void DefaultConfiguration_EverythingIsVisitedOnce() { var activeConfiguration = MixinConfiguration.ActiveConfiguration; ValidationLogData log; using (MixinConfiguration.BuildNew().EnterScope()) { log = activeConfiguration.Validate(); } var validationResults = log.GetResults(); var visitedDefinitions = new HashSet <IVisitableDefinition>(); foreach (ValidationResult result in validationResults) { var definition = result.ValidatedDefinition; Assert.That(visitedDefinitions.Contains(definition), Is.False, definition.ToString()); visitedDefinitions.Add(definition); } TargetClassDefinition bt1 = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(BaseType1)); AssertVisitedEquivalent(validationResults, bt1); TargetClassDefinition bt3 = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(BaseType3)); AssertVisitedEquivalent(validationResults, bt3); TargetClassDefinition bt6 = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(BaseType6)); AssertVisitedEquivalent(validationResults, bt6); TargetClassDefinition btWithAdditionalDependencies = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(TargetClassWithAdditionalDependencies)); AssertVisitedEquivalent(validationResults, btWithAdditionalDependencies); TargetClassDefinition targetWithSuppressAttribute = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(TargetClassSuppressingBT1Attribute)); AssertVisitedEquivalent(validationResults, targetWithSuppressAttribute); TargetClassDefinition targetWithNonIntroducedAttribute = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(TargetClassWithMixinNonIntroducingSimpleAttribute)); AssertVisitedEquivalent(validationResults, targetWithSuppressAttribute); TargetClassDefinition targetClassWinningOverMixinAddingBT1AttributeToMember = DefinitionObjectMother.GetActiveTargetClassDefinition(typeof(TargetClassWinningOverMixinAddingBT1AttributeToMember)); AssertVisitedEquivalent(validationResults, targetClassWinningOverMixinAddingBT1AttributeToMember); MixinDefinition bt1m1 = bt1.Mixins[typeof(BT1Mixin1)]; AssertVisitedEquivalent(validationResults, bt1m1); MixinDefinition bt1m2 = bt1.Mixins[typeof(BT1Mixin2)]; AssertVisitedEquivalent(validationResults, bt1m2); MixinDefinition bt3m1 = bt3.Mixins[typeof(BT3Mixin1)]; AssertVisitedEquivalent(validationResults, bt3m1); MixinDefinition bt3m2 = bt3.Mixins[typeof(BT3Mixin2)]; AssertVisitedEquivalent(validationResults, bt3m2); MixinDefinition bt3m3 = bt3.GetMixinByConfiguredType(typeof(BT3Mixin3 <,>)); AssertVisitedEquivalent(validationResults, bt3m3); MixinDefinition bt3m4 = bt3.Mixins[typeof(BT3Mixin4)]; AssertVisitedEquivalent(validationResults, bt3m4); MixinDefinition bt3m5 = bt3.Mixins[typeof(BT3Mixin5)]; AssertVisitedEquivalent(validationResults, bt3m5); MixinDefinition mixinWithSuppressedAttribute = targetWithSuppressAttribute.Mixins[typeof(MixinAddingBT1Attribute)]; AssertVisitedEquivalent(validationResults, mixinWithSuppressedAttribute); MixinDefinition mixinWithNonIntroducedAttribute = targetWithNonIntroducedAttribute.Mixins[typeof(MixinNonIntroducingSimpleAttribute)]; AssertVisitedEquivalent(validationResults, mixinWithNonIntroducedAttribute); MethodDefinition m1 = bt1.Methods[typeof(BaseType1).GetMethod("VirtualMethod", Type.EmptyTypes)]; AssertVisitedEquivalent(validationResults, m1); MethodDefinition m2 = bt1.Methods[typeof(BaseType1).GetMethod("VirtualMethod", new[] { typeof(string) })]; AssertVisitedEquivalent(validationResults, m2); MethodDefinition m3 = bt1m1.Methods[typeof(BT1Mixin1).GetMethod("VirtualMethod")]; AssertVisitedEquivalent(validationResults, m3); MethodDefinition m4 = bt1m1.Methods[typeof(BT1Mixin1).GetMethod("IntroducedMethod")]; AssertVisitedEquivalent(validationResults, m4); MethodDefinition memberWinningOverMixinAddingAttribute = targetClassWinningOverMixinAddingBT1AttributeToMember.Methods[ typeof(TargetClassWinningOverMixinAddingBT1AttributeToMember).GetMethod("VirtualMethod")]; AssertVisitedEquivalent(validationResults, memberWinningOverMixinAddingAttribute); PropertyDefinition p1 = bt1.Properties[typeof(BaseType1).GetProperty("VirtualProperty")]; AssertVisitedEquivalent(validationResults, p1); MethodDefinition m5 = p1.GetMethod; AssertVisitedEquivalent(validationResults, m5); MethodDefinition m6 = p1.SetMethod; AssertVisitedEquivalent(validationResults, m6); PropertyDefinition p2 = bt1m1.Properties[typeof(BT1Mixin1).GetProperty("VirtualProperty")]; AssertVisitedEquivalent(validationResults, p2); EventDefinition e1 = bt1.Events[typeof(BaseType1).GetEvent("VirtualEvent")]; AssertVisitedEquivalent(validationResults, e1); MethodDefinition m7 = e1.AddMethod; AssertVisitedEquivalent(validationResults, m7); MethodDefinition m8 = e1.RemoveMethod; AssertVisitedEquivalent(validationResults, m8); EventDefinition e2 = bt1m1.Events[typeof(BT1Mixin1).GetEvent("VirtualEvent")]; AssertVisitedEquivalent(validationResults, e2); InterfaceIntroductionDefinition i1 = bt1m1.InterfaceIntroductions[typeof(IBT1Mixin1)]; AssertVisitedEquivalent(validationResults, i1); MethodIntroductionDefinition im1 = i1.IntroducedMethods[typeof(IBT1Mixin1).GetMethod("IntroducedMethod")]; AssertVisitedEquivalent(validationResults, im1); PropertyIntroductionDefinition im2 = i1.IntroducedProperties[typeof(IBT1Mixin1).GetProperty("IntroducedProperty")]; AssertVisitedEquivalent(validationResults, im2); EventIntroductionDefinition im3 = i1.IntroducedEvents[typeof(IBT1Mixin1).GetEvent("IntroducedEvent")]; AssertVisitedEquivalent(validationResults, im3); AttributeDefinition a1 = bt1.CustomAttributes.GetFirstItem(typeof(BT1Attribute)); AssertVisitedEquivalent(validationResults, a1); AttributeDefinition a2 = bt1m1.CustomAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, a2); AttributeDefinition a3 = m1.CustomAttributes.GetFirstItem(typeof(BT1Attribute)); AssertVisitedEquivalent(validationResults, a3); AttributeDefinition a4 = p1.CustomAttributes.GetFirstItem(typeof(BT1Attribute)); AssertVisitedEquivalent(validationResults, a4); AttributeDefinition a5 = e1.CustomAttributes.GetFirstItem(typeof(BT1Attribute)); AssertVisitedEquivalent(validationResults, a5); AttributeDefinition a6 = im1.ImplementingMember.CustomAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, a6); AttributeDefinition a7 = im2.ImplementingMember.CustomAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, a7); AttributeDefinition a8 = im3.ImplementingMember.CustomAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, a8); AttributeIntroductionDefinition ai1 = bt1.ReceivedAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, ai1); AttributeIntroductionDefinition ai2 = m1.ReceivedAttributes.GetFirstItem(typeof(BT1M1Attribute)); AssertVisitedEquivalent(validationResults, ai2); RequiredNextCallTypeDefinition bc1 = bt3.RequiredNextCallTypes[typeof(IBaseType34)]; AssertVisitedEquivalent(validationResults, bc1); RequiredMethodDefinition bcm1 = bc1.Methods[typeof(IBaseType34).GetMethod("IfcMethod")]; AssertVisitedEquivalent(validationResults, bcm1); RequiredTargetCallTypeDefinition ft1 = bt3.RequiredTargetCallTypes[typeof(IBaseType32)]; AssertVisitedEquivalent(validationResults, ft1); RequiredMethodDefinition fm1 = ft1.Methods[typeof(IBaseType32).GetMethod("IfcMethod")]; AssertVisitedEquivalent(validationResults, fm1); RequiredMixinTypeDefinition rmt1 = btWithAdditionalDependencies.RequiredMixinTypes[typeof(IMixinWithAdditionalClassDependency)]; AssertVisitedEquivalent(validationResults, rmt1); RequiredMixinTypeDefinition rmt2 = btWithAdditionalDependencies.RequiredMixinTypes[typeof(MixinWithNoAdditionalDependency)]; AssertVisitedEquivalent(validationResults, rmt2); ComposedInterfaceDependencyDefinition cid1 = bt6.ComposedInterfaceDependencies[typeof(ICBT6Mixin1)]; AssertVisitedEquivalent(validationResults, cid1); TargetCallDependencyDefinition td1 = bt3m1.TargetCallDependencies[typeof(IBaseType31)]; AssertVisitedEquivalent(validationResults, td1); NextCallDependencyDefinition bd1 = bt3m1.NextCallDependencies[typeof(IBaseType31)]; AssertVisitedEquivalent(validationResults, bd1); MixinDependencyDefinition md1 = btWithAdditionalDependencies.Mixins[typeof(MixinWithAdditionalClassDependency)].MixinDependencies[typeof(MixinWithNoAdditionalDependency)]; AssertVisitedEquivalent(validationResults, md1); SuppressedAttributeIntroductionDefinition suppressedAttribute1 = mixinWithSuppressedAttribute.SuppressedAttributeIntroductions.GetFirstItem(typeof(BT1Attribute)); AssertVisitedEquivalent(validationResults, suppressedAttribute1); NonAttributeIntroductionDefinition nonIntroducedAttribute1 = mixinWithNonIntroducedAttribute.NonAttributeIntroductions.GetFirstItem(typeof(SimpleAttribute)); AssertVisitedEquivalent(validationResults, nonIntroducedAttribute1); NonAttributeIntroductionDefinition nonIntroducedAttribute2 = memberWinningOverMixinAddingAttribute.Overrides[0].NonAttributeIntroductions[0]; AssertVisitedEquivalent(validationResults, nonIntroducedAttribute2); }