public static MethodSlot[] FindInvalidMethods(Type projectionType, params MethodCollection[] collections) { var methodNames = collections.SelectMany(x => x.MethodNames).Distinct().ToArray(); var invalidMethods = projectionType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => !x.HasAttribute <MartenIgnoreAttribute>()) .Where(x => x.DeclaringType.Assembly != typeof(MethodCollection).Assembly) .Where(x => x.DeclaringType != typeof(object)) .Where(x => !methodNames.Contains(x.Name)) .Select(x => MethodSlot.InvalidMethodName(x, methodNames)) .ToList(); foreach (var collection in collections) { // We won't validate the methods that come through inline Lambdas foreach (var method in collection.Methods) { method.Validate(collection); collection.validateMethod(method); // hook for unusual rules } invalidMethods.AddRange(collection.Methods.Where(x => x.Errors.Any())); } return(invalidMethods.ToArray()); }
internal override void validateMethod(MethodSlot method) { if (!method.Method.GetParameters().Any()) { method.AddError($"ShouldDelete() requires at least one argument (the event type, the aggregate type, or IQuerySession)"); } }
internal override void validateMethod(MethodSlot method) { if (!method.DeclaredByAggregate && method.Method.GetParameters().All(x => x.ParameterType != AggregateType)) { method.AddError($"Aggregate type '{AggregateType.FullNameInCode()}' is required as a parameter"); } }
public void AddLambda <T>(T lambda, Type eventType) { if (eventType == null) { throw new ArgumentNullException(nameof(eventType)); } if (eventType.IsGenericType && eventType.Closes(typeof(IEvent <>))) { eventType = eventType.GetGenericArguments().Single(); } var name = LambdaName + (++_lambdaNumber).ToString(); var method = lambda.GetType().GetMethod("Invoke"); var setter = new Setter(typeof(T), name) { InitialValue = lambda }; var slot = new MethodSlot(setter, method, eventType); Methods.Add(slot); if (method.IsAsync()) { IsAsync = true; } }
public static MethodSlot InvalidMethodName(MethodInfo methodInfo, string[] methodNames) { var slot = new MethodSlot(methodInfo, null); slot._errors.Add($"Unrecognized method name '{methodInfo.Name}'. Either mark with [MartenIgnore] or use one of {methodNames.Select(x => $"'{x}'").Join(", ")}"); return(slot); }
public ApplyMethodCall(MethodSlot slot) : base(slot.HandlerType, (MethodInfo)slot.Method) { EventType = slot.EventType; if (slot.Setter != null) { Target = slot.Setter; } }
public MaybeDeleteFrame(MethodSlot slot) : base(slot.Method.As <MethodInfo>().IsAsync()) { EventType = slot.EventType; Maybe = new MethodCall(slot.HandlerType, (MethodInfo)slot.Method) { Target = slot.Setter }; }
public ShouldDeleteFrame(MethodSlot slot) : base(slot.Method.As <MethodInfo>().IsAsync()) { EventType = slot.EventType; Maybe = new MethodCall(slot.HandlerType, (MethodInfo)slot.Method) { Target = slot.Setter }; Maybe.ReturnVariable.OverrideName(Maybe.ReturnVariable.Usage + ++_number); }
public CreateAggregateFrame(MethodSlot slot) : base(slot.HandlerType, (MethodInfo)slot.Method) { ReturnAction = ReturnAction.Return; EventType = slot.EventType; if (slot.Setter != null) { Target = slot.Setter; } }
public MaybeDeleteFrame(Type aggregateType, Type identityType, MethodSlot slot) : base(slot.Method.As <MethodInfo>().IsAsync()) { _aggregateType = aggregateType; _identityType = identityType; EventType = slot.EventType; Maybe = new MethodCall(slot.HandlerType, (MethodInfo)slot.Method) { Target = slot.Setter }; }
private void addMethodSlot(MethodInfo method, bool declaredByAggregate) { if (method.IsPublic) { var slot = new MethodSlot(method, AggregateType) { HandlerType = declaredByAggregate ? AggregateType : ProjectionType, DeclaredByAggregate = declaredByAggregate }; Methods.Add(slot); } else { var parameterTypes = new List <Type>(); if (declaredByAggregate) { parameterTypes.Add(AggregateType); } else { parameterTypes.Add(ProjectionType); } parameterTypes.AddRange(method.GetParameters().Select(x => x.ParameterType)); var parameters = parameterTypes.Select(Expression.Parameter).ToArray(); Type baseType = null; if (method.ReturnType == typeof(void)) { baseType = _actionBaseTypes[parameterTypes.Count]; } else { parameterTypes.Add(method.ReturnType); baseType = _funcBaseTypes[parameterTypes.Count]; } var lambdaType = baseType.MakeGenericType(parameterTypes.ToArray()); var loaderType = typeof(LambdaLoader <>).MakeGenericType(lambdaType); var loader = (ILambdaLoader)Activator.CreateInstance(loaderType); loader.Add(this, method, AggregateType, parameters); } }
public CreateMethodCollection(Type projectionType, Type aggregateType) : base(MethodName, projectionType, aggregateType) { _validArgumentTypes.Add(typeof(IQuerySession)); _validReturnTypes.Fill(aggregateType); _validReturnTypes.Add(typeof(Task <>).MakeGenericType(aggregateType)); var constructors = aggregateType .GetConstructors() .Where(x => x.GetParameters().Length == 1); foreach (var constructor in constructors) { var slot = new MethodSlot(constructor, projectionType, aggregateType); Methods.Add(slot); } }
public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, IDocumentMapping aggregateMapping, MethodSlot slot) { return(new ApplyMethodCall(slot)); }
public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, IDocumentMapping aggregateMapping, MethodSlot slot) { return(new ShouldDeleteFrame(slot)); }
public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, DocumentMapping aggregateMapping, MethodSlot slot) { if (slot.Method is ConstructorInfo) { return(new AggregateConstructorFrame(slot)); } return(new CreateAggregateFrame(slot)); }
internal override void validateMethod(MethodSlot method) { // Nothing, no special rules }
public AggregateConstructorFrame(MethodSlot slot) { _slot = slot; _argType = slot.Method.GetParameters().Single().ParameterType; }
internal abstract void validateMethod(MethodSlot method);
public abstract IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, IDocumentMapping aggregateMapping, MethodSlot slot);
public override IEventHandlingFrame CreateEventTypeHandler(Type aggregateType, DocumentMapping aggregateMapping, MethodSlot slot) { return(new MaybeDeleteFrame(aggregateType, aggregateMapping.IdType, slot)); }