text:
using MvvmCross.Platform;
using MvvmCross.Platform.Core;
using MvvmCross.Platform.Exceptions;
using MvvmCross.Platform.Platform;
using System;
using System.Threading.Tasks;
using System.Threading;

namespace MvvmCross.Plugins.DownloadCache
{
    [Preserve(AllMembers = true)]
	public class MvxDynamicImageHelper<T>
        : IMvxImageHelper<T>
        where T : class
    {
        #region ImageState enum

        public enum ImageState
        {
            DefaultShown,
            ErrorShown,
            HttpImageShown
        }

        #endregion ImageState enum

        private ImageState _currentImageState = ImageState.DefaultShown;

		private CancellationTokenSource _cancellationSource;

        private string _defaultImagePath;

        private string _errorImagePath;

        private string _imageUrl;

        public string DefaultImagePath
        {
            get { return _defaultImagePath; }
            set
            {
                if (_defaultImagePath == value)
                    return;
                _defaultImagePath = value;
                OnImagePathChanged().ConfigureAwait(false);

                if (string.IsNullOrEmpty(_errorImagePath))
                    ErrorImagePath = value;
            }
        }

        public string ErrorImagePath
        {
            get { return _errorImagePath; }
            set
            {
                if (_errorImagePath == value)
                    return;
                _errorImagePath = value;
                OnImagePathChanged().ConfigureAwait(false);
            }
        }

        public string ImageUrl
        {
            get { return _imageUrl; }
            set
            {
                if (_imageUrl == value)
                    return;
                _imageUrl = value;
                RequestImageAsync(_imageUrl).ConfigureAwait(false);
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion IDisposable Members

        ~MvxDynamicImageHelper()
        {
            Dispose(false);
        }

        public event EventHandler<MvxValueEventArgs<T>> ImageChanged;

        public int MaxWidth { get; set; }
        public int MaxHeight { get; set; }

        private void FireImageChanged(T image)
        {
            var handler = ImageChanged;
            handler?.Invoke(this, new MvxValueEventArgs<T>(image));
        }

        private async Task RequestImageAsync(string imageSource)
        {
			if (_cancellationSource != null)
			{
				_cancellationSource.Cancel ();
				_cancellationSource = null;
			}

			var cancelTokenSource = new CancellationTokenSource ();
			var cancelToken = cancelTokenSource.Token;
			_cancellationSource = cancelTokenSource;

            FireImageChanged(null);

            if (string.IsNullOrEmpty(imageSource))
            {
                await ShowDefaultImage().ConfigureAwait(false);
                return;
            }

            if (imageSource.ToUpper().StartsWith("HTTP"))
            {
                await NewHttpImageRequestedAsync().ConfigureAwait(false);

                var error = false;
                try
                {
                    var cache = Mvx.Resolve<IMvxImageCache<T>>();
                    var image = await cache.RequestImage(imageSource).ConfigureAwait(false);

					if (cancelToken.IsCancellationRequested) {
						return;
					}

                    if (image == null)
                        await ShowErrorImage().ConfigureAwait(false);
                    else
                        NewImageAvailable(image);
                }
                catch (Exception ex)
                {
                    Mvx.Trace("failed to download image {0} : {1}", imageSource, ex.ToLongString());
                    error = true;
                }

                if (error)
                    await HttpImageErrorSeenAsync().ConfigureAwait(false);
            }
            else
            {
                try
                {
                    var image = await ImageFromLocalFileAsync(imageSource).ConfigureAwait(false);

					if (cancelToken.IsCancellationRequested) {
						return;
					}

                    if (image == null)
                        await ShowErrorImage().ConfigureAwait(false);
                    else
                        NewImageAvailable(image);
                }
                catch (Exception ex)
                {
                    Mvx.Error(ex.Message);
                }
            }
        }

        private Task OnImagePathChanged()
        {
            switch (_currentImageState)
            {
                case ImageState.ErrorShown:
                    return ShowErrorImage();

                default:
                    return ShowDefaultImage();
            }
        }

        private Task ShowDefaultImage()
        {
            return ShowLocalFileAsync(_defaultImagePath);
        }

        private Task ShowErrorImage()
        {
            return ShowLocalFileAsync(_errorImagePath);
        }

        private async Task ShowLocalFileAsync(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                FireImageChanged(null);
            }
            else
            {
                FireImageChanged(null);

                try
                {
                    var localImage = await ImageFromLocalFileAsync(filePath).ConfigureAwait(false);
                    if (localImage == null)
                        MvxTrace.Warning("Failed to load local image for filePath {0}", filePath);

                    FireImageChanged(localImage);
                }
                catch (Exception ex)
                {
                    Mvx.Error(ex.Message);
                }
            }
        }

        private async Task<T> ImageFromLocalFileAsync(string path)
        {
            var loader = Mvx.Resolve<IMvxLocalFileImageLoader<T>>();
            var img = await loader.Load(path, true, MaxWidth, MaxHeight).ConfigureAwait(false);
            return img.RawImage;
        }

        private Task NewHttpImageRequestedAsync()
        {
            _currentImageState = ImageState.DefaultShown;
            return ShowDefaultImage();
        }

        private Task HttpImageErrorSeenAsync()
        {
            _currentImageState = ImageState.ErrorShown;
            return ShowErrorImage();
        }

        private void NewImageAvailable(T image)
        {
            _currentImageState = ImageState.HttpImageShown;
            FireImageChanged(image);
        }

        protected virtual void Dispose(bool isDisposing)
        {
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
using System.ComponentModel;
using Common.Common;

namespace PatientManagement.DAL
{
    public class InsuranceCompany : INotifyPropertyChanged
    {
        public InsuranceCompany()
        {
            this.Address = new Address();
        }

        public InsuranceCompany(InsuranceCompany insurance)
        {
            this.Name = insurance.Name;
            this.TaxId = insurance.TaxId;
            this.Address = new Address
            {
                StreetOne = insurance.Address.StreetOne,
                StreetTwo = insurance.Address.StreetTwo,
                City = insurance.Address.City,
                State = insurance.Address.State,
                ZipCode = insurance.Address.ZipCode
            };
        }

        public string Name { get; set; }

        public string TaxId { get; set; }

        public Address Address { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


text:
export default {
  entityName: 'notifications'
}


text:
//
//  ZLPhotoTool.m
//  多选相册照片
//
//  Created by long on 15/11/30.
//  Copyright © 2015年 long. All rights reserved.
//

#import "ZLPhotoTool.h"

@implementation ZLPhotoAblumList

@end

@implementation ZLPhotoTool

static ZLPhotoTool *sharePhotoTool = nil;
+ (instancetype)sharePhotoTool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharePhotoTool = [[self alloc] init];
    });
    return sharePhotoTool;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharePhotoTool = [super allocWithZone:zone];
    });
    return sharePhotoTool;
}

#pragma mark - 获取所有相册列表
- (NSArray<ZLPhotoAblumList *> *)getPhotoAblumList
{
    NSMutableArray<ZLPhotoAblumList *> *photoAblumList = [NSMutableArray array];

    //获取所有智能相册
    PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    [smartAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL *stop) {
        //过滤掉视频和最近删除
        if (!([collection.localizedTitle isEqualToString:@"Recently Deleted"] ||
            [collection.localizedTitle isEqualToString:@"Videos"])) {
            NSArray<PHAsset *> *assets = [self getAssetsInAssetCollection:collection ascending:NO];
            if (assets.count > 0) {
                ZLPhotoAblumList *ablum = [[ZLPhotoAblumList alloc] init];
                ablum.title = [self transformAblumTitle:collection.localizedTitle];
                ablum.count = assets.count;
                ablum.headImageAsset = assets.firstObject;
                ablum.assetCollection = collection;
                [photoAblumList addObject:ablum];
            }
        }
    }];

    //获取用户创建的相册
    PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
    [userAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        NSArray<PHAsset *> *assets = [self getAssetsInAssetCollection:collection ascending:NO];
        if (assets.count > 0) {
            ZLPhotoAblumList *ablum = [[ZLPhotoAblumList alloc] init];
            ablum.title = collection.localizedTitle;
            ablum.count = assets.count;
            ablum.headImageAsset = assets.firstObject;
            ablum.assetCollection = collection;
            [photoAblumList addObject:ablum];
        }
    }];

    return photoAblumList;
}

- (NSString *)transformAblumTitle:(NSString *)title
{
    if ([title isEqualToString:@"Slo-mo"]) {
        return @"慢动作";
    } else if ([title isEqualToString:@"Recently Added"]) {
        return @"最近添加";
    } else if ([title isEqualToString:@"Favorites"]) {
        return @"最爱";
    } else if ([title isEqualToString:@"Recently Deleted"]) {
        return @"最近删除";
    } else if ([title isEqualToString:@"Videos"]) {
        return @"视频";
    } else if ([title isEqualToString:@"All Photos"]) {
        return @"所有照片";
    } else if ([title isEqualToString:@"Selfies"]) {
        return @"自拍";
    } else if ([title isEqualToString:@"Screenshots"]) {
        return @"屏幕快照";
    } else if ([title isEqualToString:@"Camera Roll"]) {
        return @"相机胶卷";
    } else if ([title isEqualToString:@"Panoramas"]) {
        return @"全景照片";
    }
    return nil;
}

- (PHFetchResult *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending
{
    PHFetchOptions *option = [[PHFetchOptions alloc] init];
    option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];
    PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:assetCollection options:option];
    return result;
}

#pragma mark - 获取相册内所有照片资源
- (NSArray<PHAsset *> *)getAllAssetInPhotoAblumWithAscending:(BOOL)ascending
{
    NSMutableArray<PHAsset *> *assets = [NSMutableArray array];

    PHFetchOptions *option = [[PHFetchOptions alloc] init];
    //ascending 为YES时,按照照片的创建时间升序排列;为NO时,则降序排列
    option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];

    PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:option];

    [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        PHAsset *asset = (PHAsset *)obj;
        [assets addObject:asset];
    }];

    return assets;
}

#pragma mark - 获取指定相册内的所有图片
- (NSArray<PHAsset *> *)getAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending
{
    NSMutableArray<PHAsset *> *arr = [NSMutableArray array];

    PHFetchResult *result = [self fetchAssetsInAssetCollection:assetCollection ascending:ascending];
    [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (((PHAsset *)obj).mediaType == PHAssetMediaTypeImage) {
            [arr addObject:obj];
        }
    }];
    return arr;
}

#pragma mark - 获取asset对应的图片
- (void)requestImageForAsset:(PHAsset *)asset size:(CGSize)size resizeMode:(PHImageRequestOptionsResizeMode)resizeMode completion:(void (^)(UIImage *))completion
{
    PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
    /**
     resizeMode:对请求的图像怎样缩放。有三种选择:None,默认加载方式;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。
     deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。
     这个属性只有在 synchronous 为 true 时有效。
     */
    option.resizeMode = resizeMode;//控制照片尺寸
    //option.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;//控制照片质量
    //option.synchronous = YES;
    option.networkAccessAllowed = YES;
    //param:targetSize 即你想要的图片尺寸,若想要原尺寸则可输入PHImageManagerMaximumSize
    [[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {
        completion(image);
    }];
}

@end
// 版权属于原作者
// http://code4app.com (cn) http://code4app.net (en)
// 发布代码于最专业的源码分享网站: Code4App.com


text:
html_logo_url = "https://raw.githubusercontent.com/rusoto/rusoto/master/assets/logo-square.png"
)]
//!
<fullname>Amazon Mechanical Turk API Reference</fullname>

//!
//! If you're using the service, you're probably looking for [MechanicalTurkClient](struct.MechanicalTurkClient.html) and [MechanicalTurk](trait.MechanicalTurk.html).

mod custom;
mod generated;
pub use custom::*;
pub use generated::*;


text:
A simple program for entering info into programs that don't honour the "remember me'" option as they should.

[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Walkman100/Walkman?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

## Screenshot
[![InfoManager Screenshot][Screenshot]][Screenshot]

  [Screenshot]: http://walkman100.github.io/images/Screenshots/My_Projects/InfoManager/MainWindow.png

## Download
Get the latest version [here](https://github.com/Walkman100/InfoManager/releases), and the latest build from commit
[here](https://ci.appveyor.com/project/Walkman100/InfoManager/build/artifacts)
(note that these builds are built for the Debug config and so are not optimised)

## Data Storage
The data file that stores the entries is managed by Windows, so if you move or rename the executable the entry data is reset - unless you move the user config file to the same folder as the exe ([contact me for help](http://walkman100.github.io/contact)). They are also stored in a different folder for each version, which you will have to manually copy to keep the entry data.

## Compile requirements
See [CompileInstructions.md](https://github.com/Walkman100/gists/blob/master/CompileInstructions.md)


text:
'use strict';

/**
 * @ngdoc service
 * @name flowsimApp.socket
 * @description
 * # socket
 * Factory in the flowsimApp.
 */
angular.module('flowsimApp')
  .factory('socket', function (socketFactory) {
    // Service logic
    // ...
    var socket = socketFactory();
    socket.forward('broadcast');
    return socket;
  });


text:
<!doctype html>

  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <title>google-map-jsonld Demo</title>

  <link rel="import" href="google-map-jsonld.html">

An example of using <google-map-jsonld>:

<template id="auto-bind-demo" is="auto-binding">

  <core-ajax id="geocode"
        url="json.json"
        auto
        response="{{data}}"
        handleAs="json"></core-ajax>

  <google-map-jsonld jsonld="{{data['@graph']}}">
  </google-map-jsonld>

</template>


text:
/**
 * Created by Bryan on 2/11/14.
 */
angular.module('AssessmentEditor')

    // A RESTful factory for retrieving contacts from 'assessmentlist.json'
    .factory('assessments', ['$http', function ($http, utils) {
        var path = 'app/json/assessmentlist.json';
        var assessments = $http.get(path).then(function (resp) {
            return resp.data.assessments;
        });

        var factory = {};
        factory.all = function () {
            return assessments;
        };
        factory.get = function (id) {
            return assessments.then(function(){
                return utils.findById(contacts, id);
            })
        };
        return factory;
    }])

    .factory('utils', function () {

        return {

            // Util for finding an object by its 'id' property among an array
            findById: function findById(a, id) {
                for (var i = 0; i < a.length; i++) {
                    if (a[i].id == id) return a[i];
                }
                return null;
            },

            // Util for returning a randomKey from a collection that also isn't the current key
            newRandomKey: function newRandomKey(coll, key, currentKey){
                var randKey;
                do {
                    randKey = coll[Math.floor(coll.length * Math.random())][key];
                } while (randKey == currentKey);
                return randKey;
            }

        };

    });


text:
package sets

type MutableSetFactoryBase interface {
  Class() MutableSetClass
}

type MutableSetFactoryContext interface {
  Set
  MutableSetFactoryBase
}

type MutableSetFactoryDerived interface {
  Copy() MutableSet
  Immutable() Set
}

type MutableSetFactory interface {
  MutableSetFactoryContext
  MutableSetFactoryDerived
}

func EmbeddedMutableSetFactory(obj MutableSetFactory) MutableSetFactory {
  return &setFactory{obj, obj}
}

type setFactory struct {
  obj MutableSetFactory
  MutableSetFactoryContext
}

func (this *setFactory) Copy() MutableSet {
  return this.obj.Class().From(this.obj)
}

func (this *setFactory) Immutable() Set {
  return newWrappedSet(this.obj.Copy(), true)
}


text:
@implementation MPUIImageToNSDictionaryValueTransformer

static NSMutableDictionary *imageCache;

+ (void)load {
    imageCache = [NSMutableDictionary dictionary];
}

+ (Class)transformedValueClass
{
    return [NSDictionary class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    NSDictionary *transformedValue = nil;

    if ([value isKindOfClass:[UIImage class]]) {
        UIImage *image = value;

        NSValueTransformer *sizeTransformer = [NSValueTransformer valueTransformerForName:NSStringFromClass([MPCGSizeToNSDictionaryValueTransformer class])];
        NSValueTransformer *insetsTransformer = [NSValueTransformer valueTransformerForName:NSStringFromClass([MPUIEdgeInsetsToNSDictionaryValueTransformer class])];

        NSValue *sizeValue = [NSValue valueWithCGSize:image.size];
        NSValue *capInsetsValue = [NSValue valueWithUIEdgeInsets:image.capInsets];
        NSValue *alignmentRectInsetsValue = [NSValue valueWithUIEdgeInsets:image.alignmentRectInsets];

        NSArray *images = image.images ?: @[ image ];

        NSMutableArray *imageDictionaries = [NSMutableArray array];
        for (UIImage *frame in images) {
            NSData *imageData = UIImagePNGRepresentation(frame);
            NSString *imageDataString = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
            NSDictionary *imageDictionary = @{ @"scale": @(image.scale),
                                               @"mime_type": @"image/png",
                                               @"data": (imageData != nil ? imageDataString : [NSNull null]) };

            [imageDictionaries addObject:imageDictionary];
        }

        transformedValue = @{
           @"imageOrientation": @(image.imageOrientation),
           @"size": [sizeTransformer transformedValue:sizeValue],
           @"renderingMode": @(image.renderingMode),
           @"resizingMode": @(image.resizingMode),
           @"duration": @(image.duration),
           @"capInsets": [insetsTransformer transformedValue:capInsetsValue],
           @"alignmentRectInsets": [insetsTransformer transformedValue:alignmentRectInsetsValue],
           @"images": [imageDictionaries copy],
        };
    }

    return transformedValue;
}

- (id)reverseTransformedValue:(id)value
{
    if ([value isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictionaryValue = value;

        NSValueTransformer *insetsTransformer = [NSValueTransformer valueTransformerForName:NSStringFromClass([MPUIEdgeInsetsToNSDictionaryValueTransformer class])];

        NSArray *imagesDictionary = dictionaryValue[@"images"];
        UIEdgeInsets capInsets = [[insetsTransformer reverseTransformedValue:dictionaryValue[@"capInsets"]] UIEdgeInsetsValue];

        NSMutableArray *images = [NSMutableArray array];
        for (NSDictionary *imageDictionary in imagesDictionary) {
            NSNumber *scale = imageDictionary[@"scale"];
            UIImage *image;
            if (imageDictionary[@"url"]) {
                @synchronized(imageCache) {
                    image = [imageCache valueForKey:imageDictionary[@"url"]];
                }
                if (!image) {
                    NSURL *imageUrl = [NSURL URLWithString: imageDictionary[@"url"]];
                    NSError *error;
                    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl options:(NSDataReadingOptions)0 error:&error];
                    if (!error) {
                        image = [UIImage imageWithData:imageData scale:fminf(1.0, scale.floatValue)];
                        @synchronized(imageCache) {
                            if (image) {
                                imageCache[imageDictionary[@"url"]] = image;
                            }
                        }
                    }
                }
                if (image && imageDictionary[@"dimensions"]) {
                    NSDictionary *dimensions = imageDictionary[@"dimensions"];
                    CGSize size = CGSizeMake([dimensions[@"Width"] floatValue], [dimensions[@"Height"] floatValue]);
                    UIGraphicsBeginImageContext(size);
                    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
                    image = UIGraphicsGetImageFromCurrentImageContext();
                    UIGraphicsEndImageContext();
                }
            }
            else if (imageDictionary[@"data"] && imageDictionary[@"data"] != [NSNull null]) {
                NSData *imageData = [[NSData alloc] initWithBase64EncodedString:imageDictionary[@"data"]
                                                                        options:NSDataBase64DecodingIgnoreUnknownCharacters];
                image = [UIImage imageWithData:imageData scale:fminf(1.0, scale.floatValue)];
            }

            if (image) {
                [images addObject:image];
            }
        }

        UIImage *image = nil;

        if (images.count > 1) {
            // animated image
            image =  [UIImage animatedImageWithImages:images duration:[dictionaryValue[@"duration"] doubleValue]];
        }
        else if (images.count > 0)
        {
            image = images[0];
        }

        if (image && UIEdgeInsetsEqualToEdgeInsets(capInsets, UIEdgeInsetsZero) == NO) {
            if (dictionaryValue[@"resizingMode"]) {
                UIImageResizingMode resizingMode = (UIImageResizingMode)[dictionaryValue[@"resizingMode"] integerValue];
                image = [image resizableImageWithCapInsets:capInsets resizingMode:resizingMode];
            } else {
                image = [image resizableImageWithCapInsets:capInsets];
            }
        }

        return image;
    }

    return nil;
}

@end


text:
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Orleans.CodeGeneration;
using Orleans.Runtime.GrainDirectory;
using Orleans.Runtime.Scheduler;
using Orleans.Serialization;
using Orleans.Storage;
using Orleans.Streams;
using Orleans.Transactions;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Threading;
using Orleans.Configuration;

namespace Orleans.Runtime
{
    /// <summary>
    /// Internal class for system grains to get access to runtime object
    /// </summary>
    internal class InsideRuntimeClient : ISiloRuntimeClient, ILifecycleParticipant<ISiloLifecycle>
    {
        private readonly ILogger logger;
        private readonly ILogger invokeExceptionLogger;
        private readonly ILoggerFactory loggerFactory;
        private readonly SiloMessagingOptions messagingOptions;
        private readonly List<IDisposable> disposables;
        private readonly ConcurrentDictionary<CorrelationId, CallbackData> callbacks;
        private readonly SharedCallbackData sharedCallbackData;
        private SafeTimer callbackTimer;

        private ILocalGrainDirectory directory;
        private Catalog catalog;
        private Dispatcher dispatcher;
        private List<IIncomingGrainCallFilter> grainCallFilters;
        private SerializationManager serializationManager;
        private IHostedClient hostedClient;

        private IHostedClient HostedClient => this.hostedClient ?? (this.hostedClient = this.ServiceProvider.GetRequiredService<IHostedClient>());
        private readonly InterfaceToImplementationMappingCache interfaceToImplementationMapping = new InterfaceToImplementationMappingCache();
        private readonly GrainTypeManager typeManager;
        private readonly MessageFactory messageFactory;
        private readonly ITransactionAgent transactionAgent;
        private IGrainReferenceRuntime grainReferenceRuntime;
        private readonly IGrainCancellationTokenRuntime cancellationTokenRuntime;
        private readonly ApplicationRequestsStatisticsGroup appRequestStatistics;
        private readonly SchedulingOptions schedulingOptions;

        public InsideRuntimeClient(
            ILocalSiloDetails siloDetails,
            GrainTypeManager typeManager,
            TypeMetadataCache typeMetadataCache,
            OrleansTaskScheduler scheduler,
            IServiceProvider serviceProvider,
            MessageFactory messageFactory,
            ITransactionAgent transactionAgent,
            ILoggerFactory loggerFactory,
            IOptions<SiloMessagingOptions> messagingOptions,
            IGrainCancellationTokenRuntime cancellationTokenRuntime,
            IOptions<SchedulingOptions> schedulerOptions,
            ApplicationRequestsStatisticsGroup appRequestStatistics)
        {
            this.ServiceProvider = serviceProvider;
            this.MySilo = siloDetails.SiloAddress;
            this.disposables = new List<IDisposable>();
            this.callbacks = new ConcurrentDictionary<CorrelationId, CallbackData>();
            this.typeManager = typeManager;
            this.messageFactory = messageFactory;
            this.transactionAgent = transactionAgent;
            this.Scheduler = scheduler;
            this.ConcreteGrainFactory = new GrainFactory(this, typeMetadataCache);
            this.logger = loggerFactory.CreateLogger<InsideRuntimeClient>();
            this.invokeExceptionLogger = loggerFactory.CreateLogger($"{typeof(Grain).FullName}.InvokeException");
            this.loggerFactory = loggerFactory;
            this.messagingOptions = messagingOptions.Value;
            this.cancellationTokenRuntime = cancellationTokenRuntime;
            this.appRequestStatistics = appRequestStatistics;
            this.schedulingOptions = schedulerOptions.Value;

            this.sharedCallbackData = new SharedCallbackData(
                msg => this.UnregisterCallback(msg.Id),
                this.loggerFactory.CreateLogger<CallbackData>(),
                this.messagingOptions,
                this.appRequestStatistics);
        }

        public IServiceProvider ServiceProvider { get; }

        /// <inheritdoc />
        public ClientInvokeCallback ClientInvokeCallback { get; set; }

        public IStreamProviderRuntime CurrentStreamProviderRuntime { get; internal set; }

        public OrleansTaskScheduler Scheduler { get; }

        public IInternalGrainFactory InternalGrainFactory => this.ConcreteGrainFactory;

        private SiloAddress MySilo { get; }

        public GrainFactory ConcreteGrainFactory { get; }

        private Catalog Catalog => this.catalog ?? (this.catalog = this.ServiceProvider.GetRequiredService<Catalog>());

        private ILocalGrainDirectory Directory
            => this.directory ?? (this.directory = this.ServiceProvider.GetRequiredService<ILocalGrainDirectory>());

        private List<IIncomingGrainCallFilter> GrainCallFilters
            => this.grainCallFilters ?? (this.grainCallFilters = new List<IIncomingGrainCallFilter>(this.ServiceProvider.GetServices<IIncomingGrainCallFilter>()));

        private Dispatcher Dispatcher => this.dispatcher ?? (this.dispatcher = this.ServiceProvider.GetRequiredService<Dispatcher>());

        public IGrainReferenceRuntime GrainReferenceRuntime => this.grainReferenceRuntime ?? (this.grainReferenceRuntime = this.ServiceProvider.GetRequiredService<IGrainReferenceRuntime>());

        public void SendRequest(
            GrainReference target,
            InvokeMethodRequest request,
            TaskCompletionSource<object> context,
            string debugContext,
            InvokeMethodOptions options,
            string genericArguments = null)
        {
            var message = this.messageFactory.CreateMessage(request, options);
            EventSourceUtils.EmitEvent(message, OrleansInsideRuntimeClientEvent.SendRequestAction);
            SendRequestMessage(target, message, context, debugContext, options, genericArguments);
        }

        private void SendRequestMessage(
            GrainReference target,
            Message message,
            TaskCompletionSource<object> context,
            string debugContext,
            InvokeMethodOptions options,
            string genericArguments = null)
        {
            // fill in sender
            if (message.SendingSilo == null)
                message.SendingSilo = MySilo;
            if (!String.IsNullOrEmpty(genericArguments))
                message.GenericGrainType = genericArguments;

            SchedulingContext schedulingContext = RuntimeContext.CurrentActivationContext as SchedulingContext;

            ActivationData sendingActivation = null;
            if (schedulingContext == null)
            {
                var clientAddress = this.HostedClient.ClientAddress;
                message.SendingGrain = clientAddress.Grain;
                message.SendingActivation = clientAddress.Activation;
            }
            else
            {
                switch (schedulingContext.ContextType)
                {
                    case SchedulingContextType.SystemThread:
                        throw new ArgumentException(
                            String.Format(
                                "Trying to send a message {0} on a silo not from within grain and not from within system target (RuntimeContext is of SchedulingContextType.SystemThread type)",
                                message),
                            "context");

                    case SchedulingContextType.Activation:
                        message.SendingActivation = schedulingContext.Activation.ActivationId;
                        message.SendingGrain = schedulingContext.Activation.Grain;
                        sendingActivation = schedulingContext.Activation;
                        break;

                    case SchedulingContextType.SystemTarget:
                        message.SendingActivation = schedulingContext.SystemTarget.ActivationId;
                        message.SendingGrain = ((ISystemTargetBase) schedulingContext.SystemTarget).GrainId;
                        break;
                }
            }

            // fill in destination
            var targetGrainId = target.GrainId;
            message.TargetGrain = targetGrainId;
            if (targetGrainId.IsSystemTarget)
            {
                SiloAddress targetSilo = (target.SystemTargetSilo ?? MySilo);
                message.TargetSilo = targetSilo;
                message.TargetActivation = ActivationId.GetSystemActivation(targetGrainId, targetSilo);
                message.Category = targetGrainId.Equals(Constants.MembershipOracleId) ?
                    Message.Categories.Ping : Message.Categories.System;
            }
            if (target.IsObserverReference)
            {
                message.TargetObserverId = target.ObserverId;
            }

            if (debugContext != null)
                message.DebugContext = debugContext;

            var oneWay = (options & InvokeMethodOptions.OneWay) != 0;
            if (context == null && !oneWay)
                logger.Warn(ErrorCode.IGC_SendRequest_NullContext, "Null context {0}: {1}", message, Utils.GetStackTrace());

            if (message.IsExpirableMessage(this.messagingOptions.DropExpiredMessages))
                message.TimeToLive = this.messagingOptions.ResponseTimeout;

            if (!oneWay)
            {
                var callbackData = new CallbackData(this.sharedCallbackData, context, message);
                callbacks.TryAdd(message.Id, callbackData);
            }

            if (targetGrainId.IsSystemTarget)
            {
                // Messages to system targets bypass the task system and get sent "in-line"
                this.Dispatcher.TransportMessage(message);
            }
            else
            {
                this.Dispatcher.SendMessage(message, sendingActivation);
            }
        }

        public void SendResponse(Message request, Response response)
        {
            EventSourceUtils.EmitEvent(request, OrleansInsideRuntimeClientEvent.SendResponseAction);
            // Don't process messages that have already timed out
            if (request.IsExpired)
            {
                request.DropExpiredMessage(MessagingStatisticsGroup.Phase.Respond);
                return;
            }

            this.Dispatcher.SendResponse(request, response);
        }

        /// <summary>
        /// UnRegister a callback.
        /// </summary>
        /// <param name="id"></param>
        private void UnregisterCallback(CorrelationId id)
        {
            CallbackData ignore;
            callbacks.TryRemove(id, out ignore);
        }

        public void SniffIncomingMessage(Message message)
        {
            try
            {
                if (message.CacheInvalidationHeader != null)
                {
                    foreach (ActivationAddress address in message.CacheInvalidationHeader)
                    {
                        this.Directory.InvalidateCacheEntry(address, message.IsReturnedFromRemoteCluster);
                    }
                }

#if false
                //// 1:
                //// Also record sending activation address for responses only in the cache.
                //// We don't record sending addresses for requests, since it is not clear that this silo ever wants to send messages to the grain sending this request.
                //// However, it is sure that this silo does send messages to the sender of a reply.
                //// In most cases it will already have its address cached, unless it had a wrong outdated address cached and now this is a fresher address.
                //// It is anyway always safe to cache the replier address.
                //// 2:
                //// after further thought decided not to do it.
                //// It seems to better not bother caching the sender of a response at all,
                //// and instead to take a very occasional hit of a full remote look-up instead of this small but non-zero hit on every response.
                //if (message.Direction.Equals(Message.Directions.Response) && message.Result.Equals(Message.ResponseTypes.Success))
                //{
                //    ActivationAddress sender = message.SendingAddress;
                //    // just make sure address we are about to cache is OK and cachable.
                //    if (sender.IsComplete && !sender.Grain.IsClient && !sender.Grain.IsSystemTargetType && !sender.Activation.IsSystemTargetType)
                //    {
                //        directory.AddCacheEntry(sender);
                //    }
                //}
#endif

            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.IGC_SniffIncomingMessage_Exc, "SniffIncomingMessage has thrown exception. Ignoring.", exc);
            }
        }

        public async Task Invoke(IAddressable target, IInvokable invokable, Message message)
        {
            try
            {
                // Don't process messages that have already timed out
                if (message.IsExpired)
                {
                    message.DropExpiredMessage(MessagingStatisticsGroup.Phase.Invoke);
                    return;
                }

                RequestContextExtensions.Import(message.RequestContextData);
                if (schedulingOptions.PerformDeadlockDetection && !message.TargetGrain.IsSystemTarget)
                {
                    UpdateDeadlockInfoInRequestContext(new RequestInvocationHistory(message.TargetGrain, message.TargetActivation, message.DebugContext));
                    // RequestContext is automatically saved in the msg upon send and propagated to the next hop
                    // in RuntimeClient.CreateMessage -> RequestContextExtensions.ExportToMessage(message);
                }

                bool startNewTransaction = false;
                ITransactionInfo transactionInfo = message.TransactionInfo;

                if (message.IsTransactionRequired && transactionInfo == null)
                {
                    // TODO: this should be a configurable parameter
                    var transactionTimeout = Debugger.IsAttached ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(10);

                    // Start a new transaction
                    transactionInfo = await this.transactionAgent.StartTransaction(message.IsReadOnly, transactionTimeout);
                    startNewTransaction = true;
                }

                if (transactionInfo != null)
                {
                    TransactionContext.SetTransactionInfo(transactionInfo);
                }

                object resultObject;
                try
                {
                    var request = (InvokeMethodRequest) message.BodyObject;
                    if (request.Arguments != null)
                    {
                        CancellationSourcesExtension.RegisterCancellationTokens(target, request, this.loggerFactory, logger, this, this.cancellationTokenRuntime);
                    }

                    var invoker = invokable.GetInvoker(typeManager, request.InterfaceId, message.GenericGrainType);

                    if (invoker is IGrainExtensionMethodInvoker &&
                        !(target is IGrainExtension) &&
                        !TryInstallExtension(request.InterfaceId, invokable, message.GenericGrainType, ref invoker))
                    {
                        // We are trying the invoke a grain extension method on a grain
                        // -- most likely reason is that the dynamic extension is not installed for this grain
                        // So throw a specific exception here rather than a general InvalidCastException
                        var error = String.Format(
                            "Extension not installed on grain {0} attempting to invoke type {1} from invokable {2}",
                            target.GetType().FullName, invoker.GetType().FullName, invokable.GetType().FullName);
                        var exc = new GrainExtensionNotInstalledException(error);
                        string extraDebugInfo = null;
#if DEBUG
                        extraDebugInfo = Utils.GetStackTrace();
#endif
                        logger.Warn(ErrorCode.Stream_ExtensionNotInstalled,
                            string.Format("{0} for message {1} {2}", error, message, extraDebugInfo), exc);

                        throw exc;
                    }

                    var requestInvoker = new GrainMethodInvoker(target, request, invoker, GrainCallFilters, interfaceToImplementationMapping);
                    await requestInvoker.Invoke();
                    resultObject = requestInvoker.Result;
                }
                catch (Exception exc1)
                {
                    if (message.Direction == Message.Directions.OneWay)
                    {
                        invokeExceptionLogger.Warn(ErrorCode.GrainInvokeException,
                            "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }
                    else if (invokeExceptionLogger.IsEnabled(LogLevel.Debug))
                    {
                        invokeExceptionLogger.Debug(ErrorCode.GrainInvokeException,
                            "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }

                    if (transactionInfo != null)
                    {
                        transactionInfo.ReconcilePending();

                        // Record reason for abort, if not alread set
                        transactionInfo.RecordException(exc1, serializationManager);

                        if (startNewTransaction)
                        {
                            exc1 = transactionInfo.MustAbort(serializationManager);
                            await this.transactionAgent.Abort(transactionInfo);
                            TransactionContext.Clear();
                        }
                    }

                    // If a grain allowed an inconsistent state exception to escape and the exception originated from
                    // this activation, then deactivate it.
                    var ise = exc1 as InconsistentStateException;
                    if (ise != null && ise.IsSourceActivation)
                    {
                        // Mark the exception so that it doesn't deactivate any other activations.
                        ise.IsSourceActivation = false;

                        var activation = (target as Grain)?.Data;
                        if (activation != null)
                        {
                            invokeExceptionLogger.Info($"Deactivating {activation} due to inconsistent state.");
                            this.DeactivateOnIdle(activation.ActivationId);
                        }
                    }

                    if (message.Direction != Message.Directions.OneWay)
                    {
                        SafeSendExceptionResponse(message, exc1);
                    }
                    return;
                }

                OrleansTransactionException transactionException = null;

                if (transactionInfo != null)
                {
                    try
                    {
                        transactionInfo.ReconcilePending();
                        transactionException = transactionInfo.MustAbort(serializationManager);

                        // This request started the transaction, so we try to commit before returning,
                        // or if it must abort, tell participants that it aborted
                        if (startNewTransaction)
                        {
                            try
                            {
                                if (transactionException == null)
                                {
                                    var status = await this.transactionAgent.Resolve(transactionInfo);
                                    if (status != TransactionalStatus.Ok)
                                    {
                                        transactionException = status.ConvertToUserException(transactionInfo.Id);
                                    }
                                }
                                else
                                {
                                    await this.transactionAgent.Abort(transactionInfo);
                                }
                            }
                            finally
                            {

                                TransactionContext.Clear();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // we should never hit this, but if we do, the following message will help us diagnose
                        this.logger.LogError(e, "Error in transaction post-grain-method-invocation code");
                        throw;
                    }
                }

                if (message.Direction != Message.Directions.OneWay)
                {
                    if (transactionException != null)
                    {
                        SafeSendExceptionResponse(message, transactionException);
                    }
                    else
                    {
                        SafeSendResponse(message, resultObject);
                    }
                }
                return;
            }
            catch (Exception exc2)
            {
                logger.Warn(ErrorCode.Runtime_Error_100329, "Exception during Invoke of message: " + message, exc2);

                TransactionContext.Clear();

                if (message.Direction != Message.Directions.OneWay)
                    SafeSendExceptionResponse(message, exc2);
            }
            finally
            {
                TransactionContext.Clear();
            }
        }

        private bool TryInstallExtension(int interfaceId, IInvokable invokable, string genericGrainType, ref IGrainMethodInvoker invoker)
        {
            IGrainExtension extension = TryGetCurrentActivationData(out ActivationData activationData)
                ? activationData.ActivationServices.GetServiceByKey<int, IGrainExtension>(interfaceId)
                : this.ServiceProvider.GetServiceByKey<int, IGrainExtension>(interfaceId);

            if (extension == null)
            {
                return false;
            }

            if (!TryAddExtension(extension))
            {
                return false;
            }

            // Get the newly installed invoker for the grain extension.
            invoker = invokable.GetInvoker(typeManager, interfaceId, genericGrainType);
            return true;
        }

        private void SafeSendResponse(Message message, object resultObject)
        {
            try
            {
                SendResponse(message, new Response(this.serializationManager.DeepCopy(resultObject)));
            }
            catch (Exception exc)
            {
                logger.Warn(ErrorCode.IGC_SendResponseFailed,
                    "Exception trying to send a response: " + exc.Message, exc);
                SendResponse(message, Response.ExceptionResponse(exc));
            }
        }

        private static readonly Lazy<Func<Exception, Exception>> prepForRemotingLazy =
            new Lazy<Func<Exception, Exception>>(CreateExceptionPrepForRemotingMethod);

        private static Func<Exception, Exception> CreateExceptionPrepForRemotingMethod()
        {
            var methodInfo = typeof(Exception).GetMethod(
                "PrepForRemoting",
                BindingFlags.Instance | BindingFlags.NonPublic);

            //This was added to avoid failure on .Net Core since Remoting APIs aren't available there.
            if (methodInfo == null)
                return exc => exc;

            var method = new DynamicMethod(
                "PrepForRemoting",
                typeof(Exception),
                new[] { typeof(Exception) },
                typeof(SerializationManager).Module,
                true);
            var il = method.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, methodInfo);
            il.Emit(OpCodes.Ret);
            return (Func<Exception, Exception>)method.CreateDelegate(typeof(Func<Exception, Exception>));
        }

        private static Exception PrepareForRemoting(Exception exception)
        {
            // Call the Exception.PrepForRemoting internal method, which preserves the original stack when the exception
            // is rethrown at the remote site (and appends the call site stacktrace). If this is not done, then when the
            // exception is rethrown the original stacktrace is entire replaced.
            // Note: another commonly used approach since .NET 4.5 is to use ExceptionDispatchInfo.Capture(ex).Throw()
            // but that involves rethrowing the exception in-place, which is not what we want here, but could in theory
            // be done at the receiving end with some rework (could be tackled when we reopen #875 Avoid unnecessary use of TCS).
            prepForRemotingLazy.Value.Invoke(exception);
            return exception;
        }

        private void SafeSendExceptionResponse(Message message, Exception ex)
        {
            try
            {
                var copiedException = PrepareForRemoting((Exception)this.serializationManager.DeepCopy(ex));
                SendResponse(message, Response.ExceptionResponse(copiedException));
            }
            catch (Exception exc1)
            {
                try
                {
                    logger.Warn(ErrorCode.IGC_SendExceptionResponseFailed,
                        "Exception trying to send an exception response: " + exc1.Message, exc1);
                    SendResponse(message, Response.ExceptionResponse(exc1));
                }
                catch (Exception exc2)
                {
                    logger.Warn(ErrorCode.IGC_UnhandledExceptionInInvoke,
                        "Exception trying to send an exception. Ignoring and not trying to send again. Exc: " + exc2.Message, exc2);
                }
            }
        }

        // assumes deadlock information was already loaded into RequestContext from the message
        private static void UpdateDeadlockInfoInRequestContext(RequestInvocationHistory thisInvocation)
        {
            IList prevChain;
            object obj = RequestContext.Get(RequestContext.CALL_CHAIN_REQUEST_CONTEXT_HEADER);
            if (obj != null)
            {
                prevChain = ((IList)obj);
            }
            else
            {
                prevChain = new List<RequestInvocationHistory>();
                RequestContext.Set(RequestContext.CALL_CHAIN_REQUEST_CONTEXT_HEADER, prevChain);
            }
            // append this call to the end of the call chain. Update in place.
            prevChain.Add(thisInvocation);
        }

        public void ReceiveResponse(Message message)
        {
            EventSourceUtils.EmitEvent(message, OrleansInsideRuntimeClientEvent.ReceiveResponseAction);
            if (message.Result == Message.ResponseTypes.Rejection)
            {
                if (!message.TargetSilo.Matches(this.MySilo))
                {
                    // gatewayed message - gateway back to sender
                    if (logger.IsEnabled(LogLevel.Trace)) logger.Trace(ErrorCode.Dispatcher_NoCallbackForRejectionResp, "No callback for rejection response message: {0}", message);
                    this.Dispatcher.Transport.SendMessage(message);
                    return;
                }

                if (logger.IsEnabled(LogLevel.Debug)) logger.Debug(ErrorCode.Dispatcher_HandleMsg, "HandleMessage {0}", message);
                switch (message.RejectionType)
                {
                    case Message.RejectionTypes.DuplicateRequest:
                        // try to remove from callbackData, just in case it is still there.
                        break;
                    case Message.RejectionTypes.Overloaded:
                        break;

                    case Message.RejectionTypes.Unrecoverable:
                    // fall through & reroute
                    case Message.RejectionTypes.Transient:
                        if (message.CacheInvalidationHeader == null)
                        {
                            // Remove from local directory cache. Note that SendingGrain is the original target, since message is the rejection response.
                            // If CacheMgmtHeader is present, we already did this. Otherwise, we left this code for backward compatability.
                            // It should be retired as we move to use CacheMgmtHeader in all relevant places.
                            this.Directory.InvalidateCacheEntry(message.SendingAddress);
                        }
                        break;

                    case Message.RejectionTypes.CacheInvalidation when message.HasCacheInvalidationHeader:
                        // The message targeted an invalid (eg, defunct) activation and this response serves only to invalidate this silo's activation cache.
                        return;
                    default:
                        logger.Error(ErrorCode.Dispatcher_InvalidEnum_RejectionType,
                            "Missing enum in switch: " + message.RejectionType);
                        break;
                }
            }

            CallbackData callbackData;
            bool found = callbacks.TryRemove(message.Id, out callbackData);
            if (found)
            {
                if (message.TransactionInfo != null)
                {
                    // NOTE: Not clear if thread-safe, revise
                    callbackData.TransactionInfo.Join(message.TransactionInfo);
                }
                // IMPORTANT: we do not schedule the response callback via the scheduler, since the only thing it does
                // is to resolve/break the resolver. The continuations/waits that are based on this resolution will be scheduled as work items.
                callbackData.DoCallback(message);
            }
            else
            {
                if (logger.IsEnabled(LogLevel.Debug)) logger.Debug(ErrorCode.Dispatcher_NoCallbackForResp,
                    "No callback for response message: " + message);
            }
        }

        public string CurrentActivationIdentity
        {
            get
            {
                if (RuntimeContext.Current == null) return this.HostedClient.ToString();

                var currentActivation = this.GetCurrentActivationData();
                return currentActivation.Address.ToString();
            }
        }

        public void Reset(bool cleanup)
        {
        }

        /// <inheritdoc />
        public TimeSpan GetResponseTimeout() => this.sharedCallbackData.ResponseTimeout;

        /// <inheritdoc />
        public void SetResponseTimeout(TimeSpan timeout) => this.sharedCallbackData.ResponseTimeout = timeout;

        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (RuntimeContext.Current == null) return this.HostedClient.CreateObjectReference(obj, invoker);
            throw new InvalidOperationException("Cannot create a local object reference from a grain.");
        }

        public void DeleteObjectReference(IAddressable obj)
        {
            if (RuntimeContext.Current == null)
            {
                this.HostedClient.DeleteObjectReference(obj);
            }
            else
            {
                throw new InvalidOperationException("Cannot delete a local object reference from a grain.");
            }
        }

        public void DeactivateOnIdle(ActivationId id)
        {
            ActivationData data;
            if (!Catalog.TryGetActivationData(id, out data)) return; // already gone

            data.ResetKeepAliveRequest(); // DeactivateOnIdle method would undo / override any current "keep alive" setting, making this grain immideately avaliable for deactivation.
            Catalog.DeactivateActivationOnIdle(data);
        }

        private Task OnRuntimeInitializeStop(CancellationToken tc)
        {
            lock (disposables)
            {
                foreach (var disposable in disposables)
                {
                    try
                    {
                        disposable?.Dispose();
                    }
                    catch (Exception e)
                    {
                        logger.Warn(ErrorCode.IGC_DisposeError, "Exception while disposing: " + e.Message, e);
                    }
                }
            }
            return Task.CompletedTask;
        }

        private Task OnRuntimeInitializeStart(CancellationToken tc)
        {
            var stopWatch = Stopwatch.StartNew();
            this.serializationManager = this.ServiceProvider.GetRequiredService<SerializationManager>();
            var timerLogger = this.loggerFactory.CreateLogger<SafeTimer>();
            var minTicks = Math.Min(this.messagingOptions.ResponseTimeout.Ticks, TimeSpan.FromSeconds(1).Ticks);
            var period = TimeSpan.FromTicks(minTicks);
            this.callbackTimer = new SafeTimer(timerLogger, this.OnCallbackExpiryTick, null, period, period);
            this.disposables.Add(this.callbackTimer);

            typeManager.Start();
            stopWatch.Stop();
            this.logger.Info(ErrorCode.SiloStartPerfMeasure, $"Start InsideRuntimeClient took {stopWatch.ElapsedMilliseconds} Milliseconds");
            return Task.CompletedTask;
        }

        public IGrainTypeResolver GrainTypeResolver => typeManager.GrainTypeResolver;

        public void BreakOutstandingMessagesToDeadSilo(SiloAddress deadSilo)
        {
            foreach (var callback in callbacks)
            {
                if (deadSilo.Equals(callback.Value.Message.TargetSilo))
                {
                    callback.Value.OnTargetSiloFail();
                }
            }
        }

        public StreamDirectory GetStreamDirectory()
        {
            if (RuntimeContext.Current == null) return this.HostedClient.StreamDirectory;
            var currentActivation = GetCurrentActivationData();
            return currentActivation.GetStreamDirectory();
        }

        public Task<Tuple<TExtension, TExtensionInterface>> BindExtension<TExtension, TExtensionInterface>(Func<TExtension> newExtensionFunc)
            where TExtension : IGrainExtension
            where TExtensionInterface : IGrainExtension
        {
            if (RuntimeContext.Current == null)
            {
                return this.HostedClient.BindExtension<TExtension, TExtensionInterface>(newExtensionFunc);
            }

            if (!TryGetExtensionHandler(out TExtension extension))
            {
                extension = newExtensionFunc();
                if (!TryAddExtension(extension))
                    throw new OrleansException("Failed to register " + typeof(TExtension).Name);
            }

            IAddressable currentGrain = (RuntimeContext.CurrentActivationContext as SchedulingContext)?.Activation.GrainInstance;
            var currentTypedGrain = currentGrain.AsReference<TExtensionInterface>();

            return Task.FromResult(Tuple.Create(extension, currentTypedGrain));
        }

        public bool TryAddExtension(IGrainExtension handler)
        {
            ExtensionInvoker extensionInvoker = GetCurrentExtensionInvoker();
            var methodInvoker = TryGetExtensionMethodInvoker(this.typeManager, handler.GetType());
            if (methodInvoker == null)
                throw new InvalidOperationException("Extension method invoker was not generated for an extension interface");

            return extensionInvoker.TryAddExtension(methodInvoker, handler);
        }

        public void RemoveExtension(IGrainExtension handler)
        {
            GetCurrentExtensionInvoker().Remove(handler);
        }

        public bool TryGetExtensionHandler<TExtension>(out TExtension result) where TExtension : IGrainExtension
        {
            ExtensionInvoker invoker = GetCurrentExtensionInvoker();
            IGrainExtension untypedResult;
            if (invoker.TryGetExtensionHandler(typeof(TExtension), out untypedResult))
            {
                result = (TExtension)untypedResult;
                return true;
            }

            result = default(TExtension);
            return false;
        }

        private ExtensionInvoker GetCurrentExtensionInvoker()
        {
            ISchedulingContext context = RuntimeContext.CurrentActivationContext;
            return (context.ContextType == SchedulingContextType.SystemTarget)
                ? (context as SchedulingContext)?.SystemTarget.ExtensionInvoker
                : GetCurrentActivationData(context).ExtensionInvoker;
        }

        private ActivationData GetCurrentActivationData(ISchedulingContext context = null)
        {
            context = context ?? RuntimeContext.CurrentActivationContext;
            if (TryGetCurrentActivationData(context, out ActivationData activationData)) return activationData;
            return ThrowInvalidOperationException();
            ActivationData ThrowInvalidOperationException() => throw new InvalidOperationException("Attempting to GetCurrentActivationData when not in an activation scope");
        }

        private bool TryGetCurrentActivationData(out ActivationData activationData)
        {
            return TryGetCurrentActivationData(RuntimeContext.CurrentActivationContext, out activationData);
        }

        private bool TryGetCurrentActivationData(ISchedulingContext context, out ActivationData activationData)
        {
            activationData = (context as SchedulingContext)?.Activation;
            return (activationData != null);
        }

        internal static IGrainExtensionMethodInvoker TryGetExtensionMethodInvoker(GrainTypeManager typeManager, Type handlerType)
        {
            var interfaces = GrainInterfaceUtils.GetRemoteInterfaces(handlerType).Values;
            if (interfaces.Count != 1)
                throw new InvalidOperationException($"Extension type {handlerType.FullName} implements more than one grain interface.");

            var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(interfaces.First());
            var invoker = typeManager.GetInvoker(interfaceId);
            if (invoker != null)
                return (IGrainExtensionMethodInvoker)invoker;

            throw new ArgumentException(
                $"Provider extension handler type {handlerType} was not found in the type manager",
                nameof(handlerType));
        }

        public void Participate(ISiloLifecycle lifecycle)
        {
            lifecycle.Subscribe<InsideRuntimeClient>(ServiceLifecycleStage.RuntimeInitialize, OnRuntimeInitializeStart, OnRuntimeInitializeStop);
        }

        private void OnCallbackExpiryTick(object state)
        {
            var currentStopwatchTicks = Stopwatch.GetTimestamp();
            var responseTimeout = this.messagingOptions.ResponseTimeout;
            foreach (var pair in callbacks)
            {
                var callback = pair.Value;
                if (callback.IsCompleted) continue;
                if (callback.IsExpired(currentStopwatchTicks)) callback.OnTimeout(responseTimeout);
            }
        }
    }
}