{"record":{"id":"b9d4ab511317fa02","repo":"LuckyPennySoftware/AutoMapper","slug":"type-conditiontype-name-does-not-implement-ipr","errorCode":null,"errorMessage":"Type '{conditionType.Name}' does not implement IPreCondition<TSource, TDestination>","messagePattern":"Type '(.+?)' does not implement IPreCondition<TSource, TDestination>","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/AutoMapper/Configuration/MemberConfigurationExpression.cs","lineNumber":134,"sourceCode":"        ConditionCore((src, dest, srcMember, destMember, ctxt) => condition(src, dest, srcMember));\n    public void Condition(Func<TSource, TDestination, bool> condition) => ConditionCore((src, dest, srcMember, destMember, ctxt) => condition(src, dest));\n    public void Condition(Func<TSource, bool> condition) => ConditionCore((src, dest, srcMember, destMember, ctxt) => condition(src));\n    protected void ConditionCore(Expression<Func<TSource, TDestination, TMember, TMember, ResolutionContext, bool>> expr) =>\n        PropertyMapActions.Add(pm => pm.Condition = expr);\n    public void PreCondition<TCondition>() where TCondition : IPreCondition<TSource, TDestination>\n    {\n        var expr = CreatePreConditionExpression(typeof(TCondition));\n        PreConditionCore(expr);\n    }\n    protected Expression<Func<TSource, TDestination, ResolutionContext, bool>> CreatePreConditionExpression(Type conditionType)\n    {\n        var srcParam = Parameter(typeof(TSource));\n        var destParam = Parameter(typeof(TDestination));\n        var ctxParam = Parameter(typeof(ResolutionContext));\n\n        var conditionInstance = ServiceLocator(conditionType);\n        var interfaceType = conditionType.GetGenericInterface(typeof(IPreCondition<,>)) ??\n            throw new InvalidOperationException($\"Type '{conditionType.Name}' does not implement IPreCondition<TSource, TDestination>\");\n        var evaluateMethod = interfaceType.GetMethod(\"Evaluate\");\n\n        // Get the actual types from the interface\n        var interfaceArgs = interfaceType.GenericTypeArguments;\n        var expectedSourceType = interfaceArgs[0];\n        var expectedDestType = interfaceArgs[1];\n\n        // Cast parameters to the expected types if needed\n        var srcArg = typeof(TSource) == expectedSourceType ? srcParam : (Expression)Convert(srcParam, expectedSourceType);\n        var destArg = typeof(TDestination) == expectedDestType ? destParam : (Expression)Convert(destParam, expectedDestType);\n\n        var callExpression = Call(\n            Convert(conditionInstance, interfaceType),\n            evaluateMethod,\n            srcArg, destArg, ctxParam\n        );\n\n        return Lambda<Func<TSource, TDestination, ResolutionContext, bool>>(","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/LuckyPennySoftware/AutoMapper/blob/dfa6dd587c5854b4beee5934beb39ba6e9569b84/src/AutoMapper/Configuration/MemberConfigurationExpression.cs#L116-L152","documentation":"Thrown by PreCondition<TCondition>() when the generic type argument does not implement the IPreCondition<TSource, TDestination> interface. The CreatePreConditionExpression method calls GetGenericInterface(typeof(IPreCondition<,>)) and throws InvalidOperationException if null. This is analogous to the Condition<ICondition<,,>> check but for the simpler two-type-argument pre-condition interface.","triggerScenarios":"Calling .PreCondition<MyPreCondition>() inside a ForMember callback where MyPreCondition does not implement IPreCondition<TSource, TDestination>, or implements it with mismatched generic type arguments.","commonSituations":"Implementing the wrong interface; confusing IPreCondition with ICondition; type argument mismatch between the pre-condition's generic arguments and the mapping's source/destination types.","solutions":["Implement IPreCondition<TSource, TDestination> on your pre-condition class with the exact same generic type arguments as the mapping.","Alternatively, use one of the lambda PreCondition(...) overloads (e.g., PreCondition(src => src.IsValid)).","Verify the generic arguments match the map's TSource and TDestination."],"exampleFix":"// before — wrong interface\npublic class MyPreCondition : ICondition<Source, Dest, bool> { /* ... */ }\nCreateMap<Source, Dest>().ForMember(d => d.X, opt => opt.PreCondition<MyPreCondition>());\n\n// after — correct interface\npublic class MyPreCondition : IPreCondition<Source, Dest>\n{\n    public bool Evaluate(Source src, Dest dest, ResolutionContext ctx) => src.IsValid;\n}\nCreateMap<Source, Dest>().ForMember(d => d.X, opt => opt.PreCondition<MyPreCondition>());","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Type guard: verify a type implements IPreCondition<TSource, TDestination>\nstatic bool ImplementsPreCondition<TSource, TDestination>(Type preConditionType)\n    => preConditionType.GetGenericInterface(typeof(IPreCondition<,>)) != null;\n\n// Usage before configuring\nif (!ImplementsPreCondition<Source, Dest>(typeof(MyPreCondition)))\n    throw new InvalidOperationException($\"{nameof(MyPreCondition)} must implement IPreCondition<Source, Dest>.\");","tryCatchPattern":null,"preventionTips":["Always implement IPreCondition<TSource, TDestination> with the exact generic arguments matching the map.","Prefer lambda PreCondition(...) overloads for simple pre-conditions.","Run AssertConfigurationIsValid in tests to catch mismatches."],"tags":["configuration","precondition","interface","mapping"],"backgroundTag":null,"analyzedSha":"dfa6dd587c5854b4beee5934beb39ba6e9569b84","analyzedAt":"2026-08-13T19:56:33.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}