• Avalanche.Core
Search Results for

    Show / Hide Table of Contents
    • Avalanche.Accessor
      • Introduction
      • IAccessor
        • IAccessor
        • IListAccessor
        • IMapAccessor
        • IRecordAccessor
        • IContentAccessor
        • IOneOfAccessor
        • IAnyAccessor
      • .Net
        • Introduction
        • IList<T>
        • IDictionary<K,V>
        • FieldInfo
        • OneOfAttribute
        • StructLayoutAttribute
        • Class
      • Protobuf
        • Introduction
      • Articles
        • Dependency Injection
        • AccessorMessages
    • Avalanche.Binding
      • Introduction
    • Avalanche.Configuration
      • Introduction
      • Configuration Binding
      • ConfigurationExtensions
      • MemoryConfiguration
      • PrintTree
      • Saving IOptions
      • Yaml
    • Avalanche.Converter
      • Introduction
      • EnumConverter
      • Func<,>
      • HexConverter
      • PrimitiveConverter
      • StringConverter
    • Avalanche.Core
      • License
    • Avalanche.DataType
      • Introduction
      • DataType
        • IDataType
        • IListType
        • IMapType
        • IRecordType
        • IFieldType
        • IOneOfType
        • IAnyType
        • IStringType
        • IValueType
        • IIntegerType
        • IEnumerationType
        • IRealType
      • .Net
        • Introduction
        • IList<T>
        • IDictionary<K,V>
        • FieldInfo
        • Enum
        • OneOfAttribute
        • StructLayoutAttribute
        • Class
      • Protobuf
        • Introduction
      • Articles
        • DataTypeRequest
        • PrintTree
        • DataTypeMessages
    • Avalanche.Emit
      • Introduction
      • TypeBuilder
      • ConstructorBuilder
      • MethodBuilder
      • PropertyBuilder
      • FieldBuilder
      • Emit
      • Utilities
    • Avalanche.FileSystem
      • Introduction
      • Abstractions
        • IFileSystem
          • IFileSystemBrowse
          • IFileSystemCreateDirectory
          • IFileSystemDelete
          • IFileSystemFileAttribute
          • IFileSystemMount
          • IFileSystemMove
          • IFileSystemObserve
          • IFileSystemOpen
        • IEvent
        • IEntry
        • IOption
        • IToken
      • FileSystem
      • VirtualFileSystem
      • MemoryFileSystem
      • EmbeddedFileSystem
      • HttpFileSystem
      • Decoration
      • IFileProvider
      • Events
      • Utilities
        • Dispose
        • File Scanner
        • Visit Tree
        • File Operation
        • FilterEnumerable
        • PollingFilterWatchToken
    • Avalanche.Identity
      • Introduction
      • Identity
      • IdentityParts
      • IdentityInterner
      • IdentityComparer
      • Print Tree
      • IdentityAccessors
        • Introduction
        • TypeName
    • Avalanche.Localization
      • Introduction
      • Localization
      • LocalizationFile
      • LocalizationFiles
      • LocalizationFileSystem
      • LocalizationFileFormat
      • LocalizationLine
      • LocalizationLines
      • TemplateFormat
      • CultureProvider
      • FallbackCultureProvider
      • ResourceManager
      • LocalizationError
      • Microsoft.Extensions
        • Introduction
        • DependencyInjection
        • FileProvider
        • Logging
        • ITextLocalizer
        • IFileLocalizer
        • Localization
      • Asp.Net
        • Introduction
        • Supplying localization
        • Inject to pages
        • Culture Assigned
        • Minimalistic Api
        • Diagnostics
      • Pluralization
        • Introduction
        • Multiple plural parameters
        • Custom PluralRules
        • Invariant Culture
        • Unit Prefix
        • IPluralRule
        • IPluralNumber
        • IPluralRules
        • CLDRs
        • Unicode.CLDR40
        • Unicode.CLDR41
        • Unicode.CLDR42
      • Articles
        • Alphabet localization
        • Benchmarks
        • Caching
        • Class Library
        • Demo
        • Diagnostics
        • Embedded resources
        • Emplacement
        • File localization
        • Text localization
        • Printing templates
    • Avalanche.Message
      • Introduction
      • IMessage
      • IMessageProvider
      • IMessageDescription
      • IMessageDescriptions
      • MessageLevel
      • Message printing
      • Messages and Exceptions
      • Microsoft.Extensions
        • DependencyInjection
      • Articles
        • Aggregate Messages
        • Localization
        • Logging
        • Validation
    • Avalanche.Options
      • Introduction
      • OptionsExtensions
      • OptionsMonitorCast
    • Avalanche.Service
      • Introduction
      • Service
        • Introduction
        • IService
        • IServiceDisposable
        • IServiceDecoration
        • IServiceCast
        • IServiceObservable
        • IServiceContainer
        • Construction
        • Query
        • CancellationToken
        • CachePolicy
        • Scope
      • Handler
        • Introduction
        • IHandler
        • IHandlerCast
        • IHandlerDecoration
        • IHandlerWithOrder
        • CancellationToken
        • Cyclicity
        • Delegates
        • Invokable
        • ExportAttribute
        • OrderAttribute
        • PrintTree
        • Recursion
      • Query
        • Introduction
        • IQuery
        • IQueryCast
        • IQueryDecoration
      • Entry
        • Introduction
        • IEntry
        • IEntryCast
        • IEntryDecoration
        • IEntryObservable
        • IEntryVisitable
        • EntryState
      • Request
        • Introduction
        • IRequest
        • IRequestFor
        • IRequestToBeCached
        • IRequestToBeDisposed
        • RequestAttribute
        • ContextParameterAttribute
        • Print Tree
      • Dependency Injection
        • Introduction
        • Asp.Net
        • ServiceRequest<T>
        • Decorating a service
        • Handler
        • CachePolicy
        • CancellationToken
        • QueryLogger
        • IHostBuilder
      • Examples
        • NodeCount
        • Expression
        • Mapper
      • Articles
        • Benchmarks
        • Error Handling
        • ServiceMessages
    • Avalanche.StatusCode
      • Introduction
      • HResult
        • Introduction
        • HResult.Facilities
        • BasicMessages
        • RpcMessages
        • DispatchMessages
        • StorageMessages
        • ItfMessages
        • Win32Messages
        • WindowsMessages
        • SspiMessages
        • CertMessages
        • MediaServerMessages
        • SetupApiMessages
        • ScardMessages
        • ComPlusMessages
        • ClrMessages
        • UserModeFilterManagerMessages
        • GraphicsMessages
        • TpmServicesMessages
        • TpmSoftwareMessages
        • PlaMessages
        • FveMessages
        • FwpMessages
        • NdisMessages
        • DltMessages
      • System
        • Introduction
        • AccessControlMessages
        • AggregateMessages
        • AppDomainMessages
        • ArgumentMessages
        • ArgumentNullMessages
        • ArgumentOutOfRangeMessages
        • ArithmeticMessages
        • ArrayMessages
        • AssemblyMessages
        • BadImageFormatMessages
        • CodeContractMessages
        • CodePageMessages
        • CollectionsMessages
        • CompilerServiceMessages
        • CryptographyMessages
        • CultureMessages
        • DiagnosticsMessages
        • EventSourceMessages
        • ExecutionEngineMessages
        • FormatMessages
        • HostProtectionMessages
        • IOMessages
        • IndexOutOfRangeMessages
        • InteropServiceMessages
        • InvalidCastMessages
        • InvalidOperationMessages
        • IsolatedStorageMessages
        • LazyMessages
        • MarshalerMessages
        • MemoryMessages
        • MiscellaneousMessages
        • NotImplementedMessages
        • NotSupportedMessages
        • ObjectDisposedMessages
        • OperationCanceledMessages
        • OverflowMessages
        • PlatformMessages
        • PolicyMessages
        • PrincipalMessages
        • ProgramMessages
        • ReferenceMessages
        • ReflectionMessages
        • RegionMessages
        • RemotingMessages
        • ResourcesMessages
        • SecurityMessages
        • SerializationMessages
        • StackMessages
        • TaskMessages
        • TextMessages
        • ThreadingMessages
        • TimeZoneMessages
        • TypeMessages
        • XmlMessages
      • HttpStatusCode
      • OpcUaStatusCode
    • Avalanche.Template
      • Introduction
      • TemplateFormats
      • ITemplatePrintable
      • ITemplateFormatPrintable
      • ITemplateText
      • ITemplateBreakdown
      • ITemplateFormat
      • ITemplateFormats
      • Extract Arguments
      • Emplacement
    • Avalanche.Tokenizer
      • Introduction
      • IToken
      • ITokenizer
      • Tokenizers
    • Avalanche.Utilities
      • Introduction
      • Collections
        • Tuples
        • StructList
        • ArrayList
        • BijectionMap
        • LocakableDictionary
        • LockableList
        • MapList
        • Pipe
        • RingQueue
        • EnumerableExtensions
        • TupleUtilities
        • ArrayUtilities
      • Comparers
        • IGraphComparer
        • IGraphComparable
        • AlphaNumericComparer
        • EnumerableComparer
        • EnumerableGraphComparer
        • ReferenceComparer
        • KeyValuePairComparer
        • DefaultComparerProvider
        • RecordComparer
      • Cloners
        • ICloner
        • IGraphCloner
        • IGraphCloneable
        • ListCloner
        • DictionaryCloner
        • FieldCloner
        • PassthroughCloner
        • RecordCloner
        • ClonerProvider
      • Dispose
        • IDisposeAttachable
        • IDisposeBelatable
      • Provider
        • Introduction
        • ProviderBase
        • Delegate
        • Pipe
        • Cache
        • ResultCapture
        • AsReadOnly
        • AsService
        • IProviderEvent
      • Record
        • IRecordDescription
        • IFieldDescription
        • IConstructorDescription
        • IConstructionDescription
        • IParameterDescription
        • IRecordProviders
        • RecordDelegates
          • RecordCreate
          • RecordClone
          • RecordCopy
          • IRecordDelegates
        • FieldDelegates
          • FieldRead
          • FieldWrite
          • RecreateWith
          • IFieldDelegates
      • Reflection
        • EnumDescription
      • String
        • IEscaper
        • UnicodeString
        • Hex
      • Miscellaneous
        • IIdGenerator
        • Permutation
        • IReadOnly
        • IUserDataContainer
        • ITreeNode
        • Void
    • Avalanche.Writer
      • Introduction
      • ConstantWriter
      • Context
      • ConvertWriter
      • DefaultConstructor
      • DelegateWriter
      • PassthroughWriter
      • Referer
      • TypeCast
      • Writer
      • WriterPipe
      • WriterMessages

    IHandler

    IHandler<Request,Response> is an interface for classes that process Request queries.

    /// <summary>Handler that processes <typeparamref name="Request"/> types.</summary>
    public interface IHandler<in Request, out Response> : IHandlerT where Request : notnull
    {
        /// <summary>Handle <paramref name="query"/>. </summary>
        /// <param name="query">Query object that contains request and response</param>
        /// <exception cref="Exception">Throw on unexpected runtime error. The caller should mark the error as <see cref="EntryStatus.Error"/>.</exception>
        void Handle(IQuery<Request, Response> query);
    }
    

    IHandlerAsync<Request,Response> is for classes that process Request queries asynchronously.

    /// <summary>Handler that processes <typeparamref name="Request"/> types.</summary>
    public interface IHandlerAsync<in Request, out Response> : IHandlerAsyncT where Request : notnull
    {
        /// <summary>Handle <paramref name="query"/>. </summary>
        /// <param name="query">Query object that contains request and response</param>
        /// <exception cref="Exception">Throw on unexpected runtime error. The caller should mark the error as <see cref="EntryStatus.Error"/>.</exception>
        Task HandleAsync(IQuery<Request, Response> query);
    }
    

    IHandler is for classes that process all types of queries.

    /// <summary>Handler with generic method that processes all request response types.</summary>
    public interface IHandler : IHandlerBaseSync
    {
        /// <summary>Handle <paramref name="query"/>. </summary>
        /// <param name="query">Query object that contains request and response</param>
        /// <exception cref="Exception">Throw on unexpected runtime error. The caller should mark the error as <see cref="EntryStatus.Error"/>.</exception>
        void Handle<Request, Response>(IQuery<Request, Response> query) where Request : notnull;
    }
    

    IHandlerAsync is for classes that process all types of queries asynchronously.

    /// <summary>Handler with generic method that processes all request response types.</summary>
    public interface IHandlerAsync : IHandlerBaseAsync
    {
        /// <summary>Handle <paramref name="query"/>. </summary>
        /// <param name="query">Query object that contains request and response</param>
        /// <exception cref="Exception">Throw on unexpected runtime error. The caller should mark the error as <see cref="EntryStatus.Error"/>.</exception>
        Task HandleAsync<Request, Response>(IQuery<Request, Response> query) where Request : notnull;
    }
    

    Implementation

    IHandler<Request, Response> handles a specific Request type, and returns a specific Response type.

    public class Handler : IHandler<TypeRequest, Type>
    {
        public void Handle(IQuery<TypeRequest, Type> query)
        {
            // Assign result
            query.Response.SetValue(typeof(string));
        }
    }
    

    IHandler<object, object> is forwarded with all requests classes and structs. This, however, causes value-typed requests to be boxed, which adds a bit of heap garbage.

    public class Handler5 : IHandler<object, object>
    {
        public void Handle(IQuery<object, object> query)
        {
            // Already handled
            if (query.Handled()) return;
            // Assign result
            query.Response.SetValue(typeof(string));
        }
    }
    

    IHandlerAsync<Request, Response> and IHandlerAsync process queries asynchronously.

    public class DownloadUrl : IHandlerAsync<string, string>
    {
        public async Task HandleAsync(IQuery<string, string> query)
        {
            // Already handled
            if (query.Handled()) return;
            // Create client
            WebClient client = new WebClient();
            // Get url
            string url = query.Request;
            // Download content
            string content = await client.DownloadStringTaskAsync(url);
            // Write result
            query.Response.SetValue(content);
        }
    }
    

    IHandlerBase interface allows generic method type parameters Handle<T>(IQuery<,>).

    public class Handler13 : IHandlerBase
    {
        [Order(1000)]
        public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query)
        {
        }
    }
    

    And same for async method Task HandleAsync<T>(IQuery<,>).

    public class Handler14 : IHandlerBase
    {
        [Order(1000)]
        public Task HandleAsync<T>(IQuery<ScopedServiceRequest<T>, object> query)
        {
            return Task.Delay(1);
        }
    }
    

    where constraint can be used with generics Handle method.

    public class Handler15 : IHandlerBase
    {
        public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) where T : IList<T> { }
    }
    

    MethodArgumentConstraints-property can be used to list generics method argument constraints if where is not expressive enough.

    public class Handler16 : IHandlerBase
    {
        /// <summary>Additional type constraints (will be picked in <see cref="IHandlerInfo"/>)</summary>
        public (string, Type)[]? MethodArgumentConstraints =>
            new (string, Type)[]
            {
                ("T", typeof(IList<>))
            };
    
        public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
    }
    

    IHandler handles all request and response types.

    public class ConsoleLogger : IHandler
    {
        public void Handle<Request, Response>(IQuery<Request, Response> query) where Request : notnull
            => Console.WriteLine(query.Response);
    }
    

    public bool HandlesRequest(Type requestType) method can be used to evaluate which request types are to be handled.

    public class Handler17 : IHandlerBase
    {
        /// <summary>Evaluate which request types to evaluate</summary>
        public bool HandlesRequest(Type requestType)
            => requestType.IsGenericType &&
            requestType.GetGenericTypeDefinition().Equals(typeof(ScopedServiceRequest<>));
    
        public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
    }
    

    If handler implements multiple IHandlerT interfaces, HandlesRequest can be assigned to specific Handle() method by introducing it in an interface.

    public class Handler18 : IMyHandler
    {
        /// <summary>Evaluate which request types to evaluate</summary>
        bool IMyHandler.HandlesRequest(Type requestType)
            => requestType.IsGenericType &&
               requestType.GetGenericTypeDefinition().Equals(typeof(ScopedServiceRequest<>));
    
        void IMyHandler.Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
    }
    public interface IMyHandler : IHandlerBase
    {
        /// <summary>Evaluate which request types to evaluate</summary>
        bool HandlesRequest(Type requestType);
        /// <summary>Handle</summary>
        void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query);
    }
    

    Customized handler interface

    Custom handler interfaces can be defined.

    public interface IServiceHandler<T> : IHandlerBaseSync
    {
        void Handle(IQuery<ScopedServiceRequest<T>, object> query);
    }
    
    public interface IServiceHandler : IHandlerBaseSync
    {
        public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query);
    }
    

    If custom handler interface has "Order" property, then the Handle() method will be associated with it in the implementation.

    public interface IServiceHandlerWithOrder<T> : IHandlerBaseSync
    {
        long? Order { get; }
        void Handle(IQuery<ScopedServiceRequest<T>, object> query);
    }
    

    Break Query

    .BreakQuery is a property to indicate that query is not to be processed by any further handlers. This does not fail the already assigned result, stops further evaluation and accepts the result.

    public class Handler20 : IHandler<TypeRequest, Type>
    {
        public void Handle(IQuery<TypeRequest, Type> query)
        {
            // Assign result
            query.Response.SetValue(typeof(string));
            // Break query process
            query.BreakQuery = true;
        }
    }
    

    Full Example

    Full example
    #pragma warning disable SYSLIB0014 
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Net;
    using System.Threading.Tasks;
    using Avalanche.Service;
    
    public class handler_handler
    {
        // <01>
        public class Handler : IHandler<TypeRequest, Type>
        {
            public void Handle(IQuery<TypeRequest, Type> query)
            {
                // Assign result
                query.Response.SetValue(typeof(string));
            }
        }
        // </01>
    
        // <02>
        public class Handler2 : IHandler<TypeRequest, Type>
        {
            public void Handle(IQuery<TypeRequest, Type> query)
            {
                // Assign result (overwrite result from earlier handler)
                query.Response.SetValue(typeof(string));
            }
        }
        // </02>
    
        // <02B>
        public class Handler2B : IHandler<TypeRequest, Type>
        {
            public void Handle(IQuery<TypeRequest, Type> query)
            {
                // Already handled by another handler
                if (query.Handled()) return;
                // Assign result
                query.Response.SetValue(typeof(string));
            }
        }
        // </02B>
    
        // <05>
        public class Handler5 : IHandler<object, object>
        {
            public void Handle(IQuery<object, object> query)
            {
                // Already handled
                if (query.Handled()) return;
                // Assign result
                query.Response.SetValue(typeof(string));
            }
        }
        // </05>
    
        // <06>
        public class ConsoleLogger : IHandler
        {
            public void Handle<Request, Response>(IQuery<Request, Response> query) where Request : notnull
                => Console.WriteLine(query.Response);
        }
        // </06>
    
        // <07>
        public class DownloadUrl : IHandlerAsync<string, string>
        {
            public async Task HandleAsync(IQuery<string, string> query)
            {
                // Already handled
                if (query.Handled()) return;
                // Create client
                WebClient client = new WebClient();
                // Get url
                string url = query.Request;
                // Download content
                string content = await client.DownloadStringTaskAsync(url);
                // Write result
                query.Response.SetValue(content);
            }
        }
        // </07>
    
        // <10>
        public interface IServiceHandler<T> : IHandlerBaseSync
        {
            void Handle(IQuery<ScopedServiceRequest<T>, object> query);
        }
        // </10>
        // <11>
        public interface IServiceHandlerWithOrder<T> : IHandlerBaseSync
        {
            long? Order { get; }
            void Handle(IQuery<ScopedServiceRequest<T>, object> query);
        }
        // </11>
    
        // <12>
        public interface IServiceHandler : IHandlerBaseSync
        {
            public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query);
        }
        // </12>
    
        // <13>
        public class Handler13 : IHandlerBase
        {
            [Order(1000)]
            public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query)
            {
            }
        }
        // </13>
    
        // <14>
        public class Handler14 : IHandlerBase
        {
            [Order(1000)]
            public Task HandleAsync<T>(IQuery<ScopedServiceRequest<T>, object> query)
            {
                return Task.Delay(1);
            }
        }
        // </14>
    
        // <15>
        public class Handler15 : IHandlerBase
        {
            public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) where T : IList<T> { }
        }
        // </15>
    
        // <16>
        public class Handler16 : IHandlerBase
        {
            /// <summary>Additional type constraints (will be picked in <see cref="IHandlerInfo"/>)</summary>
            public (string, Type)[]? MethodArgumentConstraints =>
                new (string, Type)[]
                {
                    ("T", typeof(IList<>))
                };
    
            public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
        }
        // </16>
    
    
        // <17>
        public class Handler17 : IHandlerBase
        {
            /// <summary>Evaluate which request types to evaluate</summary>
            public bool HandlesRequest(Type requestType)
                => requestType.IsGenericType &&
                requestType.GetGenericTypeDefinition().Equals(typeof(ScopedServiceRequest<>));
    
            public void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
        }
        // </17>
        // <18>
        public class Handler18 : IMyHandler
        {
            /// <summary>Evaluate which request types to evaluate</summary>
            bool IMyHandler.HandlesRequest(Type requestType)
                => requestType.IsGenericType &&
                   requestType.GetGenericTypeDefinition().Equals(typeof(ScopedServiceRequest<>));
    
            void IMyHandler.Handle<T>(IQuery<ScopedServiceRequest<T>, object> query) { }
        }
        public interface IMyHandler : IHandlerBase
        {
            /// <summary>Evaluate which request types to evaluate</summary>
            bool HandlesRequest(Type requestType);
            /// <summary>Handle</summary>
            void Handle<T>(IQuery<ScopedServiceRequest<T>, object> query);
        }
        // </18>
    
        // <20>
        public class Handler20 : IHandler<TypeRequest, Type>
        {
            public void Handle(IQuery<TypeRequest, Type> query)
            {
                // Assign result
                query.Response.SetValue(typeof(string));
                // Break query process
                query.BreakQuery = true;
            }
        }
        // </20>
    }
    #pragma warning restore SYSLIB0014 
    
    In This Article
    Back to top Copyright © Toni Kalajainen