Example #1
0
        public HUD_Object AssignHUD(string hudId, GameEntity entity)
        {
            var hud = GetHUD(entity);

            if (hud != null && hud.id.Equals(hudId))
            {
                return(hud);
            }
            else
            {
                if (hud != null)
                {
                    RemoveHUD(entity);
                }

                var prefabPath = database.Get <string>(hudId);
                var hudClone   = FactoryPool.GetPooled(prefabPath);
                hudClone.transform.SetParent(HUDParent.transform, false);
                hud = hudClone.GetComponent <HUD_Object>();

                if (hud != null)
                {
                    hud.Setup(hudId, entity);
                }
                else
                {
                    throw new NullReferenceException("Prefab " + prefabPath + " and id " + hudId + " doesn't have a HUD_Object component");
                }

                activeHUDs.Add(entity, hud);
                return(hud);
            }
        }
Example #2
0
        /// <summary>
        /// Старт ядра, запуск всех компонентов ядра, помеченных атрибутом <see cref="ImmediateStartAttribute"/>.
        /// </summary>
        public void Start()
        {
            _singletonCache = new ConcurrentDictionary <Type, object>();

            _factoryPool = new FactoryPool();
            _factoryPool.Start((TAppCore)this);

            OnStart();
            _started = true;
        }
Example #3
0
 static RefProxy <T> CreateRefProxy(FactoryPool <RefProxy <T> > pool)
 {
     return(new RefProxy <T>(pool));
 }
Example #4
0
 /// <summary>
 /// Registers an alternate messaging factory
 /// </summary>
 /// <param name="factory"></param>
 public void RegisterAlternateMessagingFactory(IMessagingFactory factory) => FactoryPool.RegisterAlternateMessagingFactory(factory);
Example #5
0
        /// <summary>
        /// Sends an outgoing message
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="outgoingMessage">Information about the message to send</param>
        /// <param name="queueType">The type of queue that should be used</param>
        /// <param name="replyTo">An optional ReplyTo queue that should be used. Only relevant in synchronous messaging</param>
        /// <param name="correlationId">The correlation id to use when sending the message. Only relevant in synchronous messaging</param>
        /// <returns></returns>
        internal async Task Send(ILogger logger, OutgoingMessage outgoingMessage, QueueType queueType, string replyTo = null, string correlationId = null)
        {
            logger.LogDebug($"Start-ServiceBusCore::Send QueueType: {queueType} replyTo: {replyTo} correlationId: {correlationId}");

            if (outgoingMessage == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage));
            }
            if (string.IsNullOrEmpty(outgoingMessage.MessageId))
            {
                throw new ArgumentNullException(nameof(outgoingMessage.MessageId));
            }
            if (outgoingMessage.Payload == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage.Payload));
            }

            var hasAgreement = true;
            // first we try and find an agreement
            var profile = await CollaborationProtocolRegistry.FindAgreementForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);

            if (profile == null)
            {
                hasAgreement = false;                 // if we don't have an agreement, we try to find the specific profile
                profile      = await CollaborationProtocolRegistry.FindProtocolForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);
            }

            logger.LogDebug($"ServiceBusCore::Send - Start retrieving and valiating certificates - correlationId: {correlationId}");
            var signature  = Settings.SigningCertificate.Certificate;
            var encryption = profile.EncryptionCertificate;

            var validator        = Core.DefaultCertificateValidator;
            var encryptionStatus = validator.Validate(encryption, X509KeyUsageFlags.DataEncipherment);
            var signatureStatus  = validator.Validate(signature, X509KeyUsageFlags.NonRepudiation);

            // this is the other parties certificate that may be out of date, not something we can fix
            if (encryptionStatus != CertificateErrors.None)
            {
                if (Core.Settings.IgnoreCertificateErrorOnSend)
                {
                    logger.LogError(EventIds.RemoteCertificate, "Remote encryption certificate is not valid");
                }
                else
                {
                    throw new MessagingException("Remote encryption certificate is not valid")
                          {
                              EventId = EventIds.RemoteCertificate
                          };
                }
            }
            // this is our certificate, something we can fix
            if (signatureStatus != CertificateErrors.None)
            {
                if (Core.Settings.IgnoreCertificateErrorOnSend)
                {
                    logger.LogError(EventIds.LocalCertificate, "Locally installed signing certificate is not valid");
                }
                else
                {
                    throw new MessagingException("Locally installed signing certificate is not valid")
                          {
                              EventId = EventIds.LocalCertificate
                          };
                }
            }
            logger.LogDebug($"ServiceBusCore::Send - End retrieving and valiating certificates - correlationId: {correlationId}");

            logger.LogDebug($"ServiceBusCore::Send - Start encrypting message - correlationId: {correlationId}");
            var protection = Core.DefaultMessageProtection;
            var stream     = protection.Protect(outgoingMessage.Payload, encryption, signature);

            logger.LogDebug($"ServiceBusCore::Send - End encrypting message - correlationId: {correlationId}");

            logger.LogDebug($"ServiceBusCore::Send - Start Create and Initialize message - correlationId: {correlationId}");
            var messagingMessage = FactoryPool.CreateMessage(logger, stream, outgoingMessage);

            if (queueType != QueueType.SynchronousReply)
            {
                messagingMessage.ReplyTo =
                    replyTo ?? await ConstructQueueName(logger, Core.Settings.MyHerId, queueType).ConfigureAwait(false);
            }

            messagingMessage.ContentType = protection.ContentType;
            messagingMessage.MessageId   = outgoingMessage.MessageId;
            // when we are replying to a synchronous message, we need to use the replyto of the original message
            messagingMessage.To =
                (queueType == QueueType.SynchronousReply) ?
                replyTo :
                await ConstructQueueName(logger, outgoingMessage.ToHerId, queueType).ConfigureAwait(false);

            messagingMessage.MessageFunction = outgoingMessage.MessageFunction;
            messagingMessage.CorrelationId   = correlationId ?? outgoingMessage.MessageId;
            messagingMessage.TimeToLive      = (queueType == QueueType.Asynchronous)
                                ? Settings.Asynchronous.TimeToLive
                                : Settings.Synchronous.TimeToLive;
            messagingMessage.ScheduledEnqueueTimeUtc = outgoingMessage.ScheduledSendTimeUtc;
            messagingMessage.FromHerId            = Core.Settings.MyHerId;
            messagingMessage.ToHerId              = outgoingMessage.ToHerId;
            messagingMessage.ApplicationTimestamp = DateTime.Now;

            if (hasAgreement)
            {
                messagingMessage.CpaId = profile.CpaId.ToString("D");
            }
            logger.LogDebug($"ServiceBusCore::Send - End Create and Initialize message - correlationId: {correlationId}");

            await Send(logger, messagingMessage, queueType, outgoingMessage.PersonalId, (LogPayload)?outgoingMessage.Payload : null).ConfigureAwait(false);

            logger.LogDebug($"End-ServiceBusCore::Send QueueType: {queueType} replyTo: {replyTo} correlationId: {correlationId}");
        }
Example #6
0
        /// <summary>
        /// Creates a new CerasSerializer, be sure to check out the tutorial.
        /// </summary>
        public CerasSerializer(SerializerConfig config = null)
        {
            Config = config ?? new SerializerConfig();

            if (Config.ExternalObjectResolver == null)
            {
                Config.ExternalObjectResolver = new ErrorResolver();
            }

            if (Config.Advanced.UseReinterpretFormatter && Config.VersionTolerance.Mode != VersionToleranceMode.Disabled)
            {
                throw new NotSupportedException("You can not use 'UseReinterpretFormatter' together with version tolerance. Either disable version tolerance, or use the old formatter for blittable types by setting 'Config.Advanced.UseReinterpretFormatter' to false.");
            }

            if (Config.Advanced.AotMode != AotMode.None && Config.VersionTolerance.Mode != VersionToleranceMode.Disabled)
            {
                throw new NotSupportedException("You can not use 'AotMode.Enabled' and version tolerance at the same time for now. If you would like this feature implemented, please open an issue on GitHub explaining your use-case, or join the Discord server.");
            }

            TypeBinder          = Config.Advanced.TypeBinder ?? new NaiveTypeBinder();
            DiscardObjectMethod = Config.Advanced.DiscardObjectMethod;

            _userResolvers = Config.OnResolveFormatter.ToArray();

            // Int, Float, Enum, ...
            _resolvers.Add(new PrimitiveResolver(this));

            // Fast native copy for unmanaged types;
            // can not handle generic structs like ValueTuple<> because they always have to be ".IsAutoLayout"
            _resolvers.Add(new ReinterpretFormatterResolver(this));

            // DateTime, Guid, KeyValuePair, Tuple, ...
            _resolvers.Add(new StandardFormatterResolver(this));

            // Array, List, Dictionary, ICollection<T>, ...
            _resolvers.Add(new CollectionFormatterResolver(this));

            // String Formatter should never be wrapped in a RefFormatter, that's too slow and not necessary
            IFormatter stringFormatter;

            if (Config.Advanced.SizeLimits.MaxStringLength < uint.MaxValue)
            {
                stringFormatter = new MaxSizeStringFormatter(Config.Advanced.SizeLimits.MaxStringLength);
            }
            else
            {
                stringFormatter = new StringFormatter();
            }
            InjectDependencies(stringFormatter);
            SetFormatters(typeof(string), stringFormatter, stringFormatter);

            //
            // Type formatter is the basis for all complex objects,
            // It is special and has its own caching system (so no wrapping in a ReferenceFormatter)
            var typeFormatter = new TypeFormatter(this);

            var runtimeType = GetType().GetType();

            SetFormatters(typeof(Type), typeFormatter, typeFormatter);
            SetFormatters(runtimeType, typeFormatter, typeFormatter);

            // MemberInfos (FieldInfo, RuntimeFieldInfo, ...)
            _resolvers.Add(new ReflectionFormatterResolver(this));

            // DynamicObjectResolver is a special case, so it is not in the resolver-list
            // That is because we only want to have specific resolvers in the resolvers-list
            _dynamicResolver = new DynamicObjectFormatterResolver(this);

            // System.Linq.Expressions - mostly handled by special configurations and DynamicFormatter, but there are some special cases.
            _resolvers.Add(new ExpressionFormatterResolver());


            //
            // Basic setup is done
            // Now calculate the protocol checksum
            _knownTypes = Config.KnownTypes.ToArray();
            if (Config.KnownTypes.Distinct().Count() != _knownTypes.Length)
            {
                // We want a *good* error message. Simply saying "can't contain any type multiple times" is not enough.
                // We have to figure out which types are there more than once.
                HashSet <Type> hashSet         = new HashSet <Type>();
                List <Type>    foundDuplicates = new List <Type>();

                for (int i = 0; i < _knownTypes.Length; i++)
                {
                    var t = _knownTypes[i];
                    if (!hashSet.Add(t))
                    {
                        if (!foundDuplicates.Contains(t))
                        {
                            foundDuplicates.Add(t);
                        }
                    }
                }

                var duplicateTypesStr = string.Join(", ", foundDuplicates.Select(t => t.Name));

                throw new Exception("KnownTypes can not contain any type multiple times! Your KnownTypes collection contains the following types more than once: " + duplicateTypesStr);
            }

            //
            // Generate checksum
            {
                foreach (var t in _knownTypes)
                {
                    ProtocolChecksum.Add(t.FullName);

                    if (t.IsEnum)
                    {
                        // Enums are a special case, they are classes internally, but they only have one field ("__value")
                        // We're always serializing them in binary with their underlying type, so there's no reason changes like Adding/Removing/Renaming
                        // enum-members could ever cause any binary incompatibility
                        //
                        // A change in the base-type however WILL cause problems!
                        ProtocolChecksum.Add(t.GetEnumUnderlyingType().FullName);
                        continue;
                    }

                    if (!t.ContainsGenericParameters)
                    {
                        var meta = GetTypeMetaData(t);
                        if (meta.PrimarySchema != null)
                        {
                            foreach (var m in meta.PrimarySchema.Members)
                            {
                                ProtocolChecksum.Add(m.MemberType.FullName);
                                ProtocolChecksum.Add(m.MemberName);

                                foreach (var a in m.MemberInfo.GetCustomAttributes(true))
                                {
                                    ProtocolChecksum.Add(a.ToString());
                                }
                            }
                        }
                    }
                }

                ProtocolChecksum.Finish();
            }

            //
            // We can already pre-warm formatters
            // - dynamic serializers generate their code
            // - reference formatters generate their wrappers
            foreach (var t in _knownTypes)
            {
                if (!t.ContainsGenericParameters)
                {
                    GetReferenceFormatter(t);
                }
            }



            //
            // Finally we need "instance data"
            _instanceDataPool = new FactoryPool <InstanceData>(p =>
            {
                var d                    = new InstanceData();
                d.CurrentRoot            = null;
                d.ObjectCache            = new ObjectCache();
                d.TypeCache              = new TypeCache(_knownTypes);
                d.EncounteredSchemaTypes = new HashSet <Type>();

                return(d);
            });
            InstanceData = _instanceDataPool.RentObject();

            if (Config.Advanced.SealTypesWhenUsingKnownTypes)
            {
                if (_knownTypes.Length > 0)
                {
                    typeFormatter.Seal();
                }
            }
        }
Example #7
0
        /// <summary>
        /// Sends an outgoing message
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="outgoingMessage">Information about the message to send</param>
        /// <param name="queueType">The type of queue that should be used</param>
        /// <param name="replyTo">An optional ReplyTo queue that should be used. Only relevant in synchronous messaging</param>
        /// <param name="correlationId">The correlation id to use when sending the message. Only relevant in synchronous messaging</param>
        /// <returns></returns>
        internal async Task Send(ILogger logger, OutgoingMessage outgoingMessage, QueueType queueType, string replyTo = null, string correlationId = null)
        {
            if (outgoingMessage == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage));
            }
            if (string.IsNullOrEmpty(outgoingMessage.MessageId))
            {
                throw new ArgumentNullException(nameof(outgoingMessage.MessageId));
            }
            if (outgoingMessage.Payload == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage.Payload));
            }

            logger.LogStartSend(queueType, outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId, outgoingMessage.PersonalId, outgoingMessage.Payload);

            var hasAgreement = true;
            // first we try and find an agreement
            var profile = await CollaborationProtocolRegistry.FindAgreementForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);

            if (profile == null)
            {
                hasAgreement = false; // if we don't have an agreement, we try to find the specific profile
                profile      = await CollaborationProtocolRegistry.FindProtocolForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);
            }

            var contentType = Core.MessageProtection.ContentType;

            if (contentType.Equals(ContentType.SignedAndEnveloped, StringComparison.OrdinalIgnoreCase))
            {
                var validator = Core.CertificateValidator;
                // Validate external part's encryption certificate
                logger.LogBeforeValidatingCertificate(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, "DataEncipherment", outgoingMessage.ToHerId, outgoingMessage.MessageId);
                var encryptionStatus = validator == null
                    ? CertificateErrors.None
                    : validator.Validate(profile.EncryptionCertificate, X509KeyUsageFlags.DataEncipherment);
                logger.LogAfterValidatingCertificate(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, "DataEncipherment", outgoingMessage.ToHerId, outgoingMessage.MessageId);

                logger.LogBeforeValidatingCertificate(outgoingMessage.MessageFunction, Core.MessageProtection.SigningCertificate.Thumbprint, Core.MessageProtection.SigningCertificate.Subject, "NonRepudiation", Core.Settings.MyHerId, outgoingMessage.MessageId);
                // Validate "our" own signature certificate
                var signatureStatus = validator == null
                    ? CertificateErrors.None
                    : validator.Validate(Core.MessageProtection.SigningCertificate, X509KeyUsageFlags.NonRepudiation);
                logger.LogAfterValidatingCertificate(outgoingMessage.MessageFunction, Core.MessageProtection.SigningCertificate.Thumbprint, Core.MessageProtection.SigningCertificate.Subject, "NonRepudiation", Core.Settings.MyHerId, outgoingMessage.MessageId);

                // this is the other parties certificate that may be out of date, not something we can fix
                if (encryptionStatus != CertificateErrors.None)
                {
                    if (Core.Settings.IgnoreCertificateErrorOnSend)
                    {
                        logger.LogError(EventIds.RemoteCertificate, $"Remote encryption certificate {profile.EncryptionCertificate?.SerialNumber} for {outgoingMessage.ToHerId.ToString()} is not valid");
                    }
                    else
                    {
                        throw new MessagingException($"Remote encryption certificate {profile.EncryptionCertificate?.SerialNumber} for {outgoingMessage.ToHerId.ToString()} is not valid")
                              {
                                  EventId = EventIds.RemoteCertificate
                              };
                    }
                }
                // this is our certificate, something we can fix
                if (signatureStatus != CertificateErrors.None)
                {
                    if (Core.Settings.IgnoreCertificateErrorOnSend)
                    {
                        logger.LogError(EventIds.LocalCertificate, $"Locally installed signing certificate {Core.MessageProtection.SigningCertificate?.SerialNumber} is not valid.\nSerial Number: {Core.MessageProtection.SigningCertificate?.SerialNumber}\nThumbprint: {Core.MessageProtection.SigningCertificate?.Thumbprint}");
                    }
                    else
                    {
                        throw new MessagingException($"Locally installed signing certificate {Core.MessageProtection.SigningCertificate?.SerialNumber} is not valid.\nSerial Number: {Core.MessageProtection.SigningCertificate?.SerialNumber}\nThumbprint: {Core.MessageProtection.SigningCertificate?.Thumbprint}")
                              {
                                  EventId = EventIds.LocalCertificate
                              };
                    }
                }
            }
            logger.LogBeforeEncryptingPayload(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);
            // Encrypt the payload
            var stream = Core.MessageProtection.Protect(outgoingMessage.Payload?.ToStream(), profile.EncryptionCertificate);

            logger.LogAfterEncryptingPayload(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);

            logger.LogBeforeFactoryPoolCreateMessage(outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);
            // Create an empty message
            var messagingMessage = FactoryPool.CreateMessage(logger, stream, outgoingMessage);

            logger.LogAfterFactoryPoolCreateMessage(outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);

            if (queueType != QueueType.SynchronousReply)
            {
                messagingMessage.ReplyTo =
                    replyTo ?? await ConstructQueueName(logger, Core.Settings.MyHerId, queueType).ConfigureAwait(false);
            }
            messagingMessage.ContentType = Core.MessageProtection.ContentType;
            messagingMessage.MessageId   = outgoingMessage.MessageId;
            // when we are replying to a synchronous message, we need to use the replyto of the original message
            messagingMessage.To =
                (queueType == QueueType.SynchronousReply) ?
                replyTo :
                await ConstructQueueName(logger, outgoingMessage.ToHerId, queueType).ConfigureAwait(false);

            messagingMessage.MessageFunction = outgoingMessage.MessageFunction;
            messagingMessage.CorrelationId   = correlationId ?? outgoingMessage.MessageId;
            messagingMessage.TimeToLive      = (queueType == QueueType.Asynchronous)
                ? Settings.Asynchronous.TimeToLive
                : Settings.Synchronous.TimeToLive;
            messagingMessage.ScheduledEnqueueTimeUtc = outgoingMessage.ScheduledSendTimeUtc;
            messagingMessage.FromHerId            = Core.Settings.MyHerId;
            messagingMessage.ToHerId              = outgoingMessage.ToHerId;
            messagingMessage.ApplicationTimestamp = DateTime.Now;

            if (hasAgreement)
            {
                messagingMessage.CpaId = profile.CpaId.ToString("D");
            }
            await Send(logger, messagingMessage, queueType, outgoingMessage.PersonalId, (LogPayload)?outgoingMessage.Payload : null).ConfigureAwait(false);

            logger.LogEndSend(queueType, messagingMessage.MessageFunction, messagingMessage.FromHerId, messagingMessage.ToHerId, messagingMessage.MessageId, outgoingMessage.PersonalId);
        }
Example #8
0
        RecursionMode _mode = RecursionMode.Idle;         // while in one mode we cannot enter the others


        public CerasSerializer(SerializerConfig config = null)
        {
            Config = config ?? new SerializerConfig();

            // Check if the config is even valid
            if (Config.EmbedChecksum && !Config.GenerateChecksum)
            {
                throw new InvalidOperationException($"{nameof(Config.GenerateChecksum)} must be true if {nameof(Config.EmbedChecksum)} is true!");
            }
            if (Config.EmbedChecksum && Config.PersistTypeCache)
            {
                throw new InvalidOperationException($"You can't have '{nameof(Config.EmbedChecksum)}' and also have '{nameof(Config.PersistTypeCache)}' because adding new types changes the checksum. You can use '{nameof(Config.GenerateChecksum)}' alone, but the checksum might change after every serialization call...");
            }

            if (Config.ExternalObjectResolver == null)
            {
                Config.ExternalObjectResolver = new ErrorResolver();
            }


            _userResolver = Config.OnResolveFormatter;

            // Int, Float, Enum, String
            _resolvers.Add(new PrimitiveResolver(this));

            _resolvers.Add(new ReflectionTypesFormatterResolver(this));
            _resolvers.Add(new KeyValuePairFormatterResolver(this));
            _resolvers.Add(new CollectionFormatterResolver(this));

            // DateTime, Guid
            _resolvers.Add(new BclFormatterResolver());

            // DynamicObjectResolver is a special case, so it is not in the resolver-list
            // That is because we only want to have specific resolvers in the resolvers-list
            _dynamicResolver = new DynamicObjectFormatterResolver(this);

            // Type formatter is the basis for all complex objects
            var typeFormatter = new TypeFormatter(this);

            _specificFormatters.Add(typeof(Type), typeFormatter);

            //if (Config.KnownTypes.Count > 0)
            //	if (Config.SealTypesWhenUsingKnownTypes)
            //		typeFormatter.Seal();

            _typeFormatter = (IFormatter <Type>)GetSpecificFormatter(typeof(Type));


            //
            // Basic setup is done
            // Now we're adding our "known types"
            // generating serializers and updating the protocol checksum
            //

            Config.KnownTypes.Seal();
            foreach (var t in Config.KnownTypes)
            {
                if (Config.GenerateChecksum)
                {
                    ProtocolChecksum.Add(t.FullName);

                    if (t.IsEnum)
                    {
                        // Enums are a special case, they are classes internally, but they only have one field ("__value")
                        // We're always serializing them in binary with their underlying type, so there's no reason changes like Adding/Removing/Renaming
                        // enum-members could ever cause any binary incompatibility
                        //
                        // A change in the base-type however WILL cause problems!
                        //
                        // Note, even without this if() everything would be ok, since the code below also writes the field-type
                        // but it is better to *explicitly* do this here and explain why we're doing it!
                        ProtocolChecksum.Add(t.GetEnumUnderlyingType().FullName);

                        continue;
                    }


                    var members = DynamicObjectFormatter <object> .GetSerializableMembers(t, Config.DefaultTargets, Config.ShouldSerializeMember);

                    foreach (var m in members)
                    {
                        ProtocolChecksum.Add(m.MemberType.FullName);
                        ProtocolChecksum.Add(m.Name);

                        foreach (var a in m.MemberInfo.GetCustomAttributes(true))
                        {
                            ProtocolChecksum.Add(a.ToString());
                        }
                    }
                }
            }

            if (Config.GenerateChecksum)
            {
                ProtocolChecksum.Finish();
            }

            //
            // Finally we need "instance data"
            _instanceDataPool = new FactoryPool <InstanceData>(p =>
            {
                var d         = new InstanceData();
                d.CurrentRoot = null;
                d.ObjectCache = new ObjectCache();
                d.TypeCache   = new ObjectCache();

                foreach (var t in Config.KnownTypes)
                {
                    d.TypeCache.RegisterObject(t);                     // For serialization
                    d.TypeCache.AddKnownType(t);                       // For deserialization
                }

                return(d);
            });
            InstanceData = _instanceDataPool.RentObject();
        }