internal static StreamSubscriptionSpecification From(ActorType actor, ActorPrototype prototype, StreamSubscriptionAttribute attribute) { if (string.IsNullOrWhiteSpace(attribute.Source)) throw InvalidSpecification(actor, "has null or whitespace only value of Source"); if (string.IsNullOrWhiteSpace(attribute.Target)) throw InvalidSpecification(actor, "has null or whitespace only value of Target"); if (attribute.Filter != null && string.IsNullOrWhiteSpace(attribute.Filter)) throw InvalidSpecification(actor, "has whitespace only value of Filter"); var parts = attribute.Source.Split(new[] {":"}, 2, StringSplitOptions.None); if (parts.Length != 2) throw InvalidSpecification(actor, $"has invalid Source specification: {attribute.Source}"); var provider = parts[0]; var source = parts[1]; var target = attribute.Target; var filter = attribute.Filter; var isRegex = source.StartsWith("/") && source.EndsWith("/"); if (!isRegex) return new MatchExact(provider, source, target, actor, prototype, filter); var pattern = source.Substring(1, source.Length - 2); return new MatchPattern(provider, pattern, target, actor, prototype, filter); }
static Func <object, bool> BuildFilter(string filter, ActorType actor, ActorPrototype prototype) { if (filter == null) { return(item => prototype.DeclaresHandlerFor(item.GetType())); } if (filter == "*") { return(item => true); } if (!filter.EndsWith("()")) { throw new InvalidOperationException("Filter string value is missing '()' function designator"); } var method = GetStaticMethod(filter, actor.Implementation); if (method == null) { throw new InvalidOperationException("Filter function should be a static method"); } return((Func <object, bool>)method.CreateDelegate(typeof(Func <object, bool>))); }
StreamSubscriptionSpecification(string provider, string source, string target, ActorType actor, ActorPrototype prototype, string filter) { Provider = provider; this.source = source; this.target = target; this.filter = BuildFilter(filter, actor, prototype); receiver = BuildReceiver(target, actor); }
public void Calls_fallback_when_handler_not_found() { var actor = new TestActor { Prototype = ActorPrototype.Define(typeof(TestActor)) }; var unknownMessage = new UnknownMessage(); object bouncedMessage = null; Assert.DoesNotThrow(() => actor.Dispatch(unknownMessage, message => bouncedMessage = message)); Assert.That(bouncedMessage, Is.SameAs(unknownMessage)); }
public static bool Matches(string stream, string target) { var actor = ActorType.From(typeof(T)); var proto = ActorPrototype.Define(actor); var specs = StreamSubscriptionSpecification.From(actor, proto); var matched = specs .Select(s => s.Match(null, stream)) .Where(m => m != StreamSubscriptionMatch.None) .ToArray(); return(matched.Any(x => x.Target == target)); }
static Func<object, bool> BuildFilter(string filter, ActorType actor, ActorPrototype prototype) { if (filter == null) return item => prototype.DeclaresHandlerFor(item.GetType()); if (filter == "*") return item => true; if (!filter.EndsWith("()")) throw new InvalidOperationException("Filter string value is missing '()' function designator"); var method = GetStaticMethod(filter, actor.Implementation); if (method == null) throw new InvalidOperationException("Filter function should be a static method"); return (Func<object, bool>)method.CreateDelegate(typeof(Func<object, bool>)); }
internal static StreamSubscriptionSpecification From(ActorType actor, ActorPrototype prototype, StreamSubscriptionAttribute attribute) { if (string.IsNullOrWhiteSpace(attribute.Source)) { throw InvalidSpecification(actor, "has null or whitespace only value of Source"); } if (string.IsNullOrWhiteSpace(attribute.Target)) { throw InvalidSpecification(actor, "has null or whitespace only value of Target"); } if (attribute.Filter != null && string.IsNullOrWhiteSpace(attribute.Filter)) { throw InvalidSpecification(actor, "has whitespace only value of Filter"); } var parts = attribute.Source.Split(new[] { ":" }, 2, StringSplitOptions.None); if (parts.Length != 2) { throw InvalidSpecification(actor, $"has invalid Source specification: {attribute.Source}"); } var provider = parts[0]; var source = parts[1]; var target = attribute.Target; var filter = attribute.Filter; var isRegex = source.StartsWith("/") && source.EndsWith("/"); if (!isRegex) { return(new MatchExact(provider, source, target, actor, prototype, filter)); } var pattern = source.Substring(1, source.Length - 2); return(new MatchPattern(provider, pattern, target, actor, prototype, filter)); }
internal static StreamSubscriptionSpecification From(ActorType actor, StreamSubscriptionAttribute attribute) { return(From(actor, ActorPrototype.Of(actor), attribute)); }
public MatchPattern(string provider, string source, string target, ActorType actor, ActorPrototype prototype, string filter) : base(provider, source, target, actor, prototype, filter) { matcher = new Regex(source, RegexOptions.Compiled); generator = new Regex(@"(?<placeholder>\{[^\}]+\})", RegexOptions.Compiled); }
internal static IEnumerable <StreamSubscriptionSpecification> From(ActorType actor, ActorPrototype prototype) { return(actor.Implementation .GetCustomAttributes <StreamSubscriptionAttribute>(inherit: true) .Select(a => From(actor, prototype, a))); }
public MatchExact(string provider, string source, string target, ActorType actor, ActorPrototype prototype, string filter) : base(provider, source, target, actor, prototype, filter) { }
internal static IEnumerable <StreamSubscriptionSpecification> From(ActorType actor) { return(From(actor, ActorPrototype.Of(actor))); }
internal static IEnumerable<StreamSubscriptionSpecification> From(ActorType actor, ActorPrototype prototype) { return actor.Implementation .GetCustomAttributes<StreamSubscriptionAttribute>(inherit: true) .Select(a => From(actor, prototype, a)); }
public static TActor Define <TActor>(this TActor actor) where TActor : Actor { Requires.NotNull(actor, nameof(actor)); actor.Prototype = ActorPrototype.Define(actor.GetType()); return(actor); }
public MatchExact(string provider, string source, string target, ActorType actor, ActorPrototype prototype, string filter) : base(provider, source, target, actor, prototype, filter) {}