// Handler mapping class. // Copyright (C) 2009-2010 Lex Li // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using GSF.Net.Snmp.Messaging; namespace GSF.Net.Snmp.Pipeline { /// /// Handler mapping class, who is used to map incoming messages to their handlers. /// [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] public sealed class HandlerMapping { #if !NET471 /// /// .NET standard 1.3 only helper. /// public static ITypeResolver TypeResolver { get; set; } = new DefaultTypeResolver(); #endif private readonly string[] _version; private readonly bool _catchAll; private readonly string _command; private readonly IMessageHandler _handler; /// /// Initializes a new instance of the class. /// /// The version. /// The command. /// The handler. [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1027:TabsMustNotBeUsed", Justification = "Reviewed. Suppression is OK here.")] public HandlerMapping(string version, string command, IMessageHandler handler) { if (version == null) { throw new ArgumentNullException(nameof(version)); } if (command == null) { throw new ArgumentNullException(nameof(command)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } _catchAll = version == "*"; _version = _catchAll ? new string[0] : version.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) ; _command = command; _handler = handler; } /// /// Initializes a new instance of the class. /// /// The version. /// The command. /// The type. /// The assembly. public HandlerMapping(string version, string command, string type, string assembly) { if (version == null) { throw new ArgumentNullException(nameof(version)); } if (command == null) { throw new ArgumentNullException(nameof(command)); } if (type == null) { throw new ArgumentNullException(nameof(type)); } if (assembly == null) { throw new ArgumentNullException(nameof(assembly)); } _catchAll = version == "*"; _version = _catchAll ? new string[0] : version.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); _command = command; _handler = CreateMessageHandler(assembly, type); } private static IMessageHandler CreateMessageHandler(string assemblyName, string type) { #if NET471 foreach (Assembly assembly in from assembly in AppDomain.CurrentDomain.GetAssemblies() let name = assembly.GetName().Name where string.Compare(name, assemblyName, StringComparison.OrdinalIgnoreCase) == 0 select assembly) { return (IMessageHandler)Activator.CreateInstance(assembly.GetType(type)); } return (IMessageHandler)Activator.CreateInstance(AppDomain.CurrentDomain.Load(assemblyName).GetType(type)); #else foreach (var assembly in from assembly in TypeResolver.GetAssemblies() let name = assembly.GetName().Name where string.Compare(name, assemblyName, StringComparison.OrdinalIgnoreCase) == 0 select assembly) { return (IMessageHandler)Activator.CreateInstance(assembly.GetType(type)); } return (IMessageHandler)Activator.CreateInstance(TypeResolver.Load(assemblyName, type)); #endif } /// /// Gets the handler. /// /// The handler. public IMessageHandler Handler { get { return _handler; } } /// /// Determines whether this instance can handle the specified message. /// /// The message. /// /// true if this instance can handle the specified message; otherwise, false. /// public bool CanHandle(ISnmpMessage message) { return VersionMatched(message) && CommandMatched(message); } private bool CommandMatched(ISnmpMessage message) { string codeString = message.Pdu().TypeCode.ToString(); return StringEquals(_command, "*") || StringEquals(_command + "RequestPdu", codeString) || StringEquals(_command + "Pdu", codeString); } private bool VersionMatched(ISnmpMessage message) { return _catchAll || _version.Any(v => StringEquals(message.Version.ToString(), v)); } private static bool StringEquals(string left, string right) { return string.Compare(left, right, StringComparison.OrdinalIgnoreCase) == 0; } } }