/// <summary>
        /// Initializes a new <see cref="StObjEngineConfiguration"/> from a <see cref="XElement"/>.
        /// </summary>
        /// <param name="e">The xml element.</param>
        public StObjEngineConfiguration(XElement e)
        {
            Throw.CheckNotNullArgument(e);

            // Global options.
            BasePath = (string?)e.Element(xBasePath);
            GeneratedAssemblyName       = (string?)e.Element(xGeneratedAssemblyName);
            TraceDependencySorterInput  = (bool?)e.Element(xTraceDependencySorterInput) ?? false;
            TraceDependencySorterOutput = (bool?)e.Element(xTraceDependencySorterOutput) ?? false;
            RevertOrderingNames         = (bool?)e.Element(xRevertOrderingNames) ?? false;
            InformationalVersion        = (string?)e.Element(xInformationalVersion);
            var sha1 = (string?)e.Element(xBaseSHA1);

            BaseSHA1 = sha1 != null?SHA1Value.Parse(sha1) : SHA1Value.Zero;

            ForceRun            = (bool?)e.Element(xForceRun) ?? false;
            GlobalExcludedTypes = new HashSet <string>(FromXml(e, xGlobalExcludedTypes, xType));

            // BinPaths.
            BinPaths = e.Elements(xBinPaths).Elements(xBinPath).Select(e => new BinPathConfiguration(e)).ToList();

            // Aspects.
            Aspects = new List <IStObjEngineAspectConfiguration>();
            foreach (var a in e.Elements(xAspect))
            {
                string type    = (string)a.AttributeRequired(xType);
                Type?  tAspect = SimpleTypeFinder.WeakResolver(type, true);
                Debug.Assert(tAspect != null);
                IStObjEngineAspectConfiguration aspect = (IStObjEngineAspectConfiguration)Activator.CreateInstance(tAspect, a) !;
                Aspects.Add(aspect);
            }
        }
示例#2
0
 public StObjEngine(IActivityMonitor monitor, StObjEngineConfiguration config)
 {
     Throw.CheckNotNullArgument(monitor);
     Throw.CheckNotNullArgument(config);
     _monitor = monitor;
     _config  = new RunningStObjEngineConfiguration(config);
 }
示例#3
0
 public CKTypeCollector(IActivityMonitor monitor,
                        IServiceProvider serviceProvider,
                        IDynamicAssembly tempAssembly,
                        Func <IActivityMonitor, Type, bool>?typeFilter = null,
                        IEnumerable <string>?names = null)
 {
     Throw.CheckNotNullArgument(monitor);
     Throw.CheckNotNullArgument(serviceProvider);
     Throw.CheckNotNullArgument(tempAssembly);
     _monitor              = monitor;
     _typeFilter           = typeFilter ?? ((m, type) => type.FullName != null);
     _tempAssembly         = tempAssembly;
     _serviceProvider      = serviceProvider;
     _assemblies           = new HashSet <Assembly>();
     _objectCollector      = new Dictionary <Type, RealObjectClassInfo?>();
     _regularTypeCollector = new Dictionary <Type, TypeAttributesCache?>();
     _roots             = new List <RealObjectClassInfo>();
     _serviceCollector  = new Dictionary <Type, AutoServiceClassInfo>();
     _serviceRoots      = new List <AutoServiceClassInfo>();
     _serviceInterfaces = new Dictionary <Type, AutoServiceInterfaceInfo?>();
     _multipleMappings  = new Dictionary <Type, MultipleImpl>();
     KindDetector       = new CKTypeKindDetector(typeFilter);
     _pocoRegistrar     = new PocoRegistrar((m, t) => (KindDetector.GetValidKind(m, t) & CKTypeKind.IsPoco) != 0, typeFilter: _typeFilter);
     _names             = names == null || !names.Any() ? new[] { String.Empty } : names.ToArray();
 }
        /// <summary>
        /// Initializes a new <see cref="StObjCollector"/>.
        /// </summary>
        /// <param name="monitor">Logger to use. Can not be null.</param>
        /// <param name="serviceProvider">Service provider used for attribute constructor injection. Must not be null.</param>
        /// <param name="traceDepencySorterInput">True to trace in <paramref name="monitor"/> the input of dependency graph.</param>
        /// <param name="traceDepencySorterOutput">True to trace in <paramref name="monitor"/> the sorted dependency graph.</param>
        /// <param name="typeFilter">Optional type filter.</param>
        /// <param name="configurator">Used to configure items. See <see cref="IStObjStructuralConfigurator"/>.</param>
        /// <param name="valueResolver">
        /// Used to explicitly resolve or alter StObjConstruct parameters and object ambient properties.
        /// See <see cref="IStObjValueResolver"/>.
        /// </param>
        /// <param name="names">Optional list of names for the final StObjMap. When null or empty, a single empty string is the default name.</param>
        public StObjCollector(IActivityMonitor monitor,
                              IServiceProvider serviceProvider,
                              bool traceDepencySorterInput              = false,
                              bool traceDepencySorterOutput             = false,
                              IStObjTypeFilter?typeFilter               = null,
                              IStObjStructuralConfigurator?configurator = null,
                              IStObjValueResolver?valueResolver         = null,
                              IEnumerable <string>?names = null)
        {
            Throw.CheckNotNullArgument(monitor);
            _monitor      = monitor;
            _tempAssembly = new DynamicAssembly();
            Func <IActivityMonitor, Type, bool>?tFilter = null;

            if (typeFilter != null)
            {
                tFilter = typeFilter.TypeFilter;
            }
            _cc            = new CKTypeCollector(_monitor, serviceProvider, _tempAssembly, tFilter, names);
            _configurator  = configurator;
            _valueResolver = valueResolver;
            if (traceDepencySorterInput)
            {
                DependencySorterHookInput = i => i.Trace(monitor);
            }
            if (traceDepencySorterOutput)
            {
                DependencySorterHookOutput = i => i.Trace(monitor);
            }

            AddWellKnownServices();
        }
示例#5
0
 /// <summary>
 /// Initializes a new <see cref="StObjMapAccessedEventArgs"/>.
 /// </summary>
 /// <param name="current">The current StObjMap. Must not be null.</param>
 /// <param name="deltaLastAccess">Time span from last access.</param>
 /// <param name="loadedTime">The current loaded time.</param>
 public StObjMapAccessedEventArgs(IStObjMap current, TimeSpan deltaLastAccess, TimeSpan loadedTime)
 {
     Throw.CheckNotNullArgument(current);
     Current             = current;
     DeltaLastAccessTime = deltaLastAccess;
     CurrentLoadedTime   = loadedTime;
 }
示例#6
0
        /// <summary>
        /// Opens a <see cref="LogReader"/> to read the content of a compressed or uncompressed stream.
        /// The stream will be closed when <see cref="LogReader.Dispose"/> will be called.
        /// </summary>
        /// <param name="seekableStream">Stream that must support Seek operations (<see cref="Stream.CanSeek"/> must be true).</param>
        /// <param name="dataOffset">
        /// An optional offset where the stream position must be initially set: this is the position of an entry in the actual (potentially uncompressed stream),
        /// not the offset in the original stream.
        /// </param>
        /// <param name="filter">An optional <see cref="MulticastFilter"/>.</param>
        /// <returns>A <see cref="LogReader"/> that will close the file when disposed.</returns>
        /// <remarks>
        /// .ckmon files exist in different file versions, depending on headers.
        /// The file can be compressed using GZipStream, in which case the header will be the magic GZIP header: 1F 8B.
        /// New header (applies to version 5), the file will start with 43 4B 4D 4F 4E (CKMON in ASCII), followed by the version number, instead of only the version number.
        /// </remarks>
        public static LogReader Open(Stream seekableStream, long dataOffset = 0, MulticastFilter?filter = null)
        {
            Throw.CheckNotNullArgument(seekableStream);
            Throw.CheckArgument(seekableStream.CanSeek);
            LogReaderStreamInfo i = LogReaderStreamInfo.OpenStream(seekableStream);
            var s = i.LogStream;

            if (dataOffset > 0)
            {
                if (s.CanSeek)
                {
                    s.Seek(dataOffset, SeekOrigin.Current);
                }
                else
                {
                    var buffer = new byte[8192];
                    int toRead;
                    while ((toRead = (int)Math.Min(8192, dataOffset)) > 0 && s.Read(buffer, 0, toRead) == toRead)
                    {
                        dataOffset -= toRead;
                    }
                }
            }
            var r = new LogReader(s, i.Version, i.HeaderLength)
            {
                CurrentFilter = filter
            };

            return(r);
        }
示例#7
0
 /// <summary>
 /// Initialization of the handler: computes the path.
 /// </summary>
 /// <param name="monitor"></param>
 public ValueTask <bool> ActivateAsync(IActivityMonitor monitor)
 {
     Throw.CheckNotNullArgument(monitor);
     using (monitor.OpenTrace($"Initializing BinaryFile handler (MaxCountPerFile = {_file.MaxCountPerFile})."))
     {
         return(ValueTask.FromResult(_file.Initialize(monitor)));
     }
 }
            /// <summary>
            /// Registers the map, the Real objects, singleton services and scoped services.
            /// Caution: this never throws, instead any exception is logged and false is returned.
            /// </summary>
            /// <param name="map">The map to register. Must not be null.</param>
            /// <returns>
            /// True on success, false if any <see cref="LogLevel.Fatal"/> or <see cref="LogLevel.Error"/> has been logged or if an exception has been thrown.
            /// </returns>
            public bool AddStObjMap(IStObjMap map)
            {
                bool result = true;

                using (Monitor.OnError(() => result = false))
                    using (Monitor.OpenInfo("Configuring Service collection from StObjMap."))
                    {
                        try
                        {
                            Throw.CheckNotNullArgument(map);
                            DoRegisterSingletonInstance(typeof(IStObjMap), map, isRealObject: true, isMultiple: false);
                            map.StObjs.ConfigureServices(this);
                            foreach (var o in map.StObjs.FinalImplementations)
                            {
                                DoRegisterSingletonInstance(o.ClassType, o.Implementation, isRealObject: true, isMultiple: false);
                                foreach (var u in o.UniqueMappings)
                                {
                                    DoRegisterSingletonInstance(u, o.Implementation, isRealObject: true, isMultiple: false);
                                }
                                foreach (var mult in o.MultipleMappings)
                                {
                                    DoRegisterSingletonInstance(mult, o.Implementation, isRealObject: true, true);
                                }
                            }
                            foreach (var s in map.Services.SimpleMappingList)
                            {
                                Register(s.ClassType, s.FinalType, s.IsScoped, allowMultipleRegistration: false);
                                foreach (var u in s.UniqueMappings)
                                {
                                    Register(u, s.FinalType, s.IsScoped, allowMultipleRegistration: false);
                                }
                                foreach (var mult in s.MultipleMappings)
                                {
                                    Register(mult, s.FinalType, s.IsScoped, allowMultipleRegistration: true);
                                }
                            }
                            foreach (var s in map.Services.ManualMappingList)
                            {
                                Register(s.ClassType, s.CreateInstance, s.IsScoped, allowMultipleRegistration: false);
                                foreach (var u in s.UniqueMappings)
                                {
                                    Register(u, s.CreateInstance, s.IsScoped, allowMultipleRegistration: false);
                                }
                                foreach (var mult in s.MultipleMappings)
                                {
                                    Register(mult, s.CreateInstance, s.IsScoped, allowMultipleRegistration: true);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Monitor.Error("While registering StObjMap.", ex);
                        }
                    }
                return(result);
            }
示例#9
0
        public static StObjEngineResult Run(IActivityMonitor monitor, StObjCollectorResult result, StObjEngineConfiguration config)
        {
            Throw.CheckNotNullArgument(monitor);
            Throw.CheckNotNullArgument(result);
            Throw.CheckNotNullArgument(config);
            Throw.CheckArgument(config.BinPaths.Select(b => b.Path).Distinct().Count() == 1);
            var e = new StObjEngine(monitor, config);

            return(e.Run(new MonoResolver(result)));
        }
 public KeyExchangeFailedEventArgs(IActivityMonitor monitor,
                                   ITrustedParty targetParty,
                                   KeyExchangeResultCode resultCode)
     : base(monitor)
 {
     Throw.CheckNotNullArgument(targetParty);
     Throw.CheckArgument(resultCode != KeyExchangeResultCode.Success);
     TargetParty = targetParty;
     ResultCode  = resultCode;
 }
示例#11
0
 public PocoRegistrar(Func <IActivityMonitor, Type, bool> actualPocoPredicate, string @namespace = "CK.GPoco", Func <IActivityMonitor, Type, bool>?typeFilter = null)
 {
     Throw.CheckNotNullArgument(actualPocoPredicate);
     Throw.CheckNotNullArgument(@namespace);
     _actualPocoPredicate = actualPocoPredicate;
     _namespace           = @namespace;
     _all        = new Dictionary <Type, PocoType?>();
     _result     = new List <List <Type> >();
     _typeFilter = typeFilter ?? ((m, type) => true);
 }
示例#12
0
 /// <summary>
 /// Applies a configuration.
 /// This is thread safe and can be called at any moment.
 /// </summary>
 /// <param name="configuration">The configuration to apply.</param>
 /// <param name="waitForApplication">
 /// True to block until this configuration has been applied.
 /// Note that another (new) configuration may have already replaced the given configuration
 /// once this call ends.
 /// </param>
 public void ApplyConfiguration(GrandOutputConfiguration configuration, bool waitForApplication = false)
 {
     Throw.CheckNotNullArgument(configuration);
     if (!configuration.InternalClone)
     {
         configuration = configuration.Clone();
         configuration.InternalClone = true;
     }
     _sink.ApplyConfiguration(configuration, waitForApplication);
 }
示例#13
0
 public KeyExchangeRequiredEventArgs(IActivityMonitor monitor,
                                     ITrustedParty targetParty,
                                     ReadOnlyMemory <byte> exchangeData,
                                     OneTimePassword?oneTimePassword)
     : base(monitor)
 {
     Throw.CheckNotNullArgument(targetParty);
     TargetParty         = targetParty;
     ExchangeRequestData = exchangeData;
     OneTimePassword     = oneTimePassword;
 }
 /// <summary>
 /// Gets the <see cref="IStObjMap"/> if no error prevents its instantiation from
 /// the <see cref="StObjMapInfo"/>.
 /// This never throws: errors are logged (a new monitor is automatically managed when <paramref name="monitor"/> is null),
 /// and null is returned.
 /// This method like all the methods that manipulates StObjMapInfo are thread/concurrency safe.
 /// </summary>
 /// <param name="info">The info.</param>
 /// <param name="monitor">Optional monitor.</param>
 /// <returns>The loaded map or null on error.</returns>
 public static IStObjMap?GetStObjMap(StObjMapInfo info, IActivityMonitor?monitor = null)
 {
     Throw.CheckNotNullArgument(info);
     if (info.StObjMap != null || info.LoadError != null)
     {
         return(info.StObjMap);
     }
     lock ( _alreadyHandled )
     {
         return(LockedGetStObjMapFromInfo(info, ref monitor));
     }
 }
 public void LogErrorAndWarnings(IActivityMonitor monitor)
 {
     Throw.CheckNotNullArgument(monitor);
     using (monitor.OpenTrace($"Collector summary:"))
     {
         if (PocoSupport == null)
         {
             monitor.Fatal($"Poco support failed!");
         }
         RealObjects.LogErrorAndWarnings(monitor);
         AutoServices.LogErrorAndWarnings(monitor);
     }
 }
 /// <summary>
 /// Initializes a new <see cref="ServiceRegister"/>.
 /// </summary>
 /// <param name="monitor">The monitor to use. Must not be null.</param>
 /// <param name="services">The service collection to configure.</param>
 /// <param name="startupServices">
 /// Optional simple container that may provide startup services. This is not used to build IRealObject
 /// (they must be independent of any "dynamic" services), however registered services become available to
 /// any <see cref="StObjContextRoot.ConfigureServicesMethodName"/> methods by parameter injection.
 /// </param>
 public ServiceRegister(IActivityMonitor monitor, IServiceCollection services, SimpleServiceContainer?startupServices = null)
 {
     Throw.CheckNotNullArgument(monitor);
     Throw.CheckNotNullArgument(services);
     Monitor         = monitor;
     Services        = services;
     StartupServices = startupServices ?? new SimpleServiceContainer();
     _registered     = new Dictionary <Type, RegType>();
     foreach (var r in services)
     {
         _registered[r.ServiceType] = RegType.PreviouslyRegistered;
     }
     AllowOverride = false;
 }
示例#17
0
        /// <summary>
        /// Binary writes a multicast closing entry.
        /// </summary>
        /// <param name="w">Binary writer to use.</param>
        /// <param name="grandOutputId">Identifier of the GrandOutput.</param>
        /// <param name="monitorId">Identifier of the monitor.</param>
        /// <param name="previousEntryType">Log type of the previous entry in the monitor..</param>
        /// <param name="previousLogTime">Time stamp of the previous entry in the monitor.</param>
        /// <param name="depth">Depth of the group (number of opened groups above).</param>
        /// <param name="level">Log level of the log entry.</param>
        /// <param name="closeTime">Time stamp of the group closing.</param>
        /// <param name="conclusions">Group conclusions.</param>
        static public void WriteCloseGroup(CKBinaryWriter w,
                                           string grandOutputId,
                                           string monitorId,
                                           LogEntryType previousEntryType,
                                           DateTimeStamp previousLogTime,
                                           int depth,
                                           LogLevel level,
                                           DateTimeStamp closeTime,
                                           IReadOnlyList <ActivityLogGroupConclusion>?conclusions)
        {
            Throw.CheckNotNullArgument(w);
            StreamLogType type = StreamLogType.TypeGroupClosed | StreamLogType.IsMultiCast;

            type = UpdateTypeWithPrevious(type, previousEntryType, ref previousLogTime);
            DoWriteCloseGroup(w, type, level, closeTime, conclusions);
            WriteMulticastFooter(w, grandOutputId, monitorId, previousEntryType, previousLogTime, depth);
        }
示例#18
0
        public async ValueTask <ISender> CreateSenderAsync(IActivityMonitor monitor,
                                                           TrustedParty audience,
                                                           ISignAlgorithm algorithm,
                                                           TimeSpan validity,
                                                           bool encrypt     = false,
                                                           uint maxUseCount = 0)
        {
            Throw.CheckNotNullArgument(monitor);
            Throw.CheckNotNullArgument(audience);
            Throw.CheckNotNullArgument(algorithm);
            Throw.CheckArgument(validity >= Configuration.MinSignatureLifetime && validity <= Configuration.MaxSignatureLifetime);
            var bestBefore = _appClock.Clock.UtcNow + validity;
            var key        = algorithm.KeyRequirement != null
                        ? await ResolveOutgoingKeyAsync(monitor, audience, algorithm.KeyRequirement, bestBefore, maxUseCount)
                        : null;

            return(new Sender(this, audience, algorithm, key, bestBefore));
        }
 CKSetupRunResult DoRunStObjSetup(StObjEngineConfiguration stObjConf, ForceSetupLevel forceSetup)
 {
     Throw.CheckNotNullArgument(stObjConf);
     using (_ckSetup.Monitor.OpenInfo($"Invoking StObjSetupRunning event."))
     {
         try
         {
             var ev = new StObjSetupRunningEventArgs(stObjConf, forceSetup);
             _stObjSetupRunning?.Invoke(this, ev);
             var ckSetupConf = new SetupConfiguration(new XDocument(ev.StObjEngineConfiguration.ToXml()), "CK.Setup.StObjEngine, CK.StObj.Engine");
             ckSetupConf.CKSetupName = _ckSetup.TestProjectName;
             return(_ckSetup.CKSetup.Run(ckSetupConf, forceSetup: ev.ForceSetup));
         }
         catch (Exception ex)
         {
             _ckSetup.Monitor.Error(ex);
             throw;
         }
     }
 }
示例#20
0
        /// <summary>
        /// Helper that copy a directory content to another one with retries.
        /// This first deletes the target directory before copying the content.
        /// </summary>
        /// <param name="monitor">The monitor to use.</param>
        /// <param name="source">The source directory.</param>
        /// <param name="target">The target directory.</param>
        /// <returns>True on success, false on error.</returns>
        public static bool SafeCopy(IActivityMonitor monitor, NormalizedPath source, NormalizedPath target)
        {
            Throw.CheckNotNullArgument(monitor);
            Throw.CheckArgument(!target.StartsWith(source) && !source.StartsWith(target));
            int tryCount = 0;

retry:
            try
            {
                var dS = new DirectoryInfo(source);
                var dT = new DirectoryInfo(target);
                if (!dS.Exists)
                {
                    monitor.Error($"Source directory '{dS.FullName}' not found.");
                    return(false);
                }
                if (!dT.Exists)
                {
                    Directory.CreateDirectory(dT.FullName);
                }
                else
                {
                    dT.Delete(recursive: true);
                }
                FileUtil.CopyDirectory(dS, dT);
            }
            catch (Exception ex)
            {
                if (++tryCount > 5)
                {
                    monitor.Error($"Failed to copy directory content from {source} to '{target}' after 5 tries.", ex);
                    return(false);
                }
                monitor.Warn($"Error while copying directory content. Retrying in {tryCount * 50} ms.", ex);
                System.Threading.Thread.Sleep(tryCount * 50);
                goto retry;
            }
            monitor.Info($"Directory content copied from '{source}' to '{target}'.");
            return(true);
        }
示例#21
0
        /// <summary>
        /// Binary writes a multicast log entry.
        /// </summary>
        /// <param name="w">Binary writer to use.</param>
        /// <param name="grandOutputId">Identifier of the GrandOutput.</param>
        /// <param name="monitorId">Identifier of the monitor.</param>
        /// <param name="previousEntryType">Log type of the previous entry in the monitor..</param>
        /// <param name="previousLogTime">Time stamp of the previous entry in the monitor.</param>
        /// <param name="depth">Depth of the line (number of opened groups above).</param>
        /// <param name="isOpenGroup">True if this the opening of a group. False for a line.</param>
        /// <param name="text">Text of the log entry.</param>
        /// <param name="level">Log level of the log entry.</param>
        /// <param name="logTime">Time stamp of the log entry.</param>
        /// <param name="tags">Tags of the log entry</param>
        /// <param name="ex">Exception of the log entry.</param>
        /// <param name="fileName">Source file name of the log entry</param>
        /// <param name="lineNumber">Source line number of the log entry</param>
        static public void WriteLog(CKBinaryWriter w,
                                    string grandOutputId,
                                    string monitorId,
                                    LogEntryType previousEntryType,
                                    DateTimeStamp previousLogTime,
                                    int depth,
                                    bool isOpenGroup,
                                    LogLevel level,
                                    DateTimeStamp logTime,
                                    string text,
                                    CKTrait tags,
                                    CKExceptionData?ex,
                                    string?fileName,
                                    int lineNumber)
        {
            Throw.CheckNotNullArgument(w);
            StreamLogType type = StreamLogType.IsMultiCast | (isOpenGroup ? StreamLogType.TypeOpenGroup : StreamLogType.TypeLine);

            type = UpdateTypeWithPrevious(type, previousEntryType, ref previousLogTime);
            DoWriteLog(w, type, level, logTime, text, tags, ex, fileName, lineNumber);
            WriteMulticastFooter(w, grandOutputId, monitorId, previousEntryType, previousLogTime, depth);
        }
 /// <summary>
 /// Attempts to load a StObjMap from an assembly.
 /// </summary>
 /// <param name="a">Already generated assembly.</param>
 /// <param name="monitor">Optional monitor for loading operation.</param>
 /// <returns>A <see cref="IStObjMap"/> that provides access to the objects graph.</returns>
 public static IStObjMap?Load(Assembly a, IActivityMonitor?monitor = null)
 {
     Throw.CheckNotNullArgument(a);
     lock ( _alreadyHandled )
     {
         var info = LockedGetMapInfo(a, ref monitor);
         if (info == null)
         {
             return(null);
         }
         var alc = AssemblyLoadContext.GetLoadContext(a);
         if (alc == null)
         {
             monitor.Warn($"Assembly '{a.FullName}' is not in any AssemblyLoadContext.");
         }
         else if (alc != AssemblyLoadContext.Default)
         {
             monitor.Warn($"Assembly '{a.FullName}' is loaded in non-default AssemblyLoadContext '{alc.Name}'.");
         }
         return(LockedGetStObjMapFromInfo(info, ref monitor));
     }
 }
示例#23
0
 public void RegisterType(Type type)
 {
     Throw.CheckNotNullArgument(type);
     if (type != typeof(object))
     {
         if (type.IsClass)
         {
             DoRegisterClass(type, out _, out _);
         }
         else if (type.IsInterface)
         {
             if (_pocoRegistrar.RegisterInterface(_monitor, type))
             {
                 RegisterAssembly(type);
             }
             RegisterRegularType(type);
         }
         else
         {
             RegisterRegularType(type);
         }
     }
 }
        /// <summary>
        /// Creates an instance of the specified type, using any available services.
        /// The strategy is to use the longest public constructor.
        /// </summary>
        /// <param name="monitor">Monitor to use.</param>
        /// <param name="t">Type of the object to create.</param>
        /// <param name="services">Available services to inject.</param>
        /// <param name="requiredParameters">Optional required parameters.</param>
        /// <returns>The object instance or null on error.</returns>
        public static object?Create(IActivityMonitor monitor, Type t, IServiceProvider services, IEnumerable <object>?requiredParameters = null)
        {
            Throw.CheckNotNullArgument(monitor);
            Throw.CheckNotNullArgument(t);
            using (monitor.OpenDebug($"Creating instance of type: {t.AssemblyQualifiedName}."))
                try
                {
                    Required required = requiredParameters == null
                            ? Array.Empty <KeyValuePair <object?, Type> >()
                            : (Required)requiredParameters.Select(r => new KeyValuePair <object?, Type>(r, r.GetType())).ToList();

                    var longestCtor = t.GetConstructors()
                                      .Select(x => ValueTuple.Create(x, x.GetParameters()))
                                      .Where(x => x.Item2.Length >= required.Count)
                                      .OrderByDescending(x => x.Item2.Length)
                                      .Select(x => new
                    {
                        Ctor       = x.Item1,
                        Parameters = x.Item2,
                        Mapped     = x.Item2
                                     .Select(p => required.FirstOrDefault(r => p.ParameterType.IsAssignableFrom(r.Value)).Key)
                                     .ToArray()
                    })
                                      .Where(x => x.Mapped.Count(m => m != null) == required.Count)
                                      .FirstOrDefault();
                    if (longestCtor == null)
                    {
                        var msg = $"Unable to find a public constructor for '{t.FullName}'.";
                        if (required.Count > 0)
                        {
                            msg += " With required parameters compatible with type: " + required.Select(r => r.Value.Name).Concatenate();
                        }
                        monitor.Error(msg);
                        return(null);
                    }
                    int failCount = 0;
                    for (int i = 0; i < longestCtor.Mapped.Length; ++i)
                    {
                        if (longestCtor.Mapped[i] == null)
                        {
                            var p        = longestCtor.Parameters[i];
                            var resolved = services.GetService(p.ParameterType);
                            if (resolved == null && !p.HasDefaultValue)
                            {
                                monitor.Error($"Resolution failed for parameter '{p.Name}', type: '{p.ParameterType}'.");
                                ++failCount;
                            }
                            longestCtor.Mapped[i] = resolved;
                        }
                    }
                    if (failCount > 0)
                    {
                        monitor.Error($"Unable to resolve parameters for '{t.FullName}'. Considered longest constructor: {longestCtor.Ctor}.");
                        return(null);
                    }
                    return(longestCtor.Ctor.Invoke(longestCtor.Mapped));
                }
                catch (Exception ex)
                {
                    monitor.Error($"While instantiating {t.FullName}.", ex);
                    return(null);
                }
        }
 /// <summary>
 /// Initializes a new <see cref="AutomaticServicesConfigurationEventArgs"/>.
 /// </summary>
 /// <param name="map">The current StObjMap. Must not be null.</param>
 /// <param name="serviceRegister">The service register.</param>
 public AutomaticServicesConfigurationEventArgs(IStObjMap map, StObjContextRoot.ServiceRegister serviceRegister)
 {
     Throw.CheckNotNullArgument(map);
     StObjMap        = map;
     ServiceRegister = serviceRegister;
 }
示例#26
0
 public StObjEngineResult Run(IStObjCollectorResultResolver resolver)
 {
     Throw.CheckNotNullArgument(resolver);
     return(DoRun(resolver));
 }
示例#27
0
 /// <summary>
 /// Creates a MonitorTraceListener instance.
 /// </summary>
 /// <param name="grandOutput">The <see cref="Monitoring.GrandOutput"/> to send traces to.</param>
 /// <param name="failFast">
 /// When true <see cref="Environment.FailFast(string)"/> will terminate the application on <see cref="Debug.Assert(bool)"/>, <see cref="Trace.Assert(bool)"/>,
 /// <see cref="Debug.Fail(string)"/> and <see cref="Trace.Fail(string)"/>.
 /// See this <see cref="MonitorTraceListener"/>'s remarks section to understand why this should be false.
 /// </param>
 public MonitorTraceListener(GrandOutput grandOutput, bool failFast)
 {
     Throw.CheckNotNullArgument(grandOutput);
     GrandOutput = grandOutput;
     FailFast    = failFast;
 }
示例#28
0
 /// <summary>
 /// Produces a string description of this <see cref="NullableTypeTree"/>.
 /// </summary>
 /// <param name="b">The string builder to use.</param>
 /// <param name="withNamespace">True to include the types' namespace and enclosing types (non generic) if any.</param>
 /// <returns>The string builder.</returns>
 public StringBuilder ToString(StringBuilder b, bool withNamespace = false)
 {
     Throw.CheckNotNullArgument(b);
     if (Type.IsArray)
     {
         RawSubTypes[0].ToString(b, withNamespace);
         b.Append('[').Append(',', Type.GetArrayRank() - 1).Append(']');
     }
     else
     {
         if ((Kind & NullabilityTypeKind.IsGenericType) != 0)
         {
             bool isTuple = Type.IsValueTuple();
             if (isTuple)
             {
                 b.Append('(');
             }
             else
             {
                 var n = CodeWriterExtensions.GetTypeAlias(Type);
                 if (n == null)
                 {
                     n = Type.Name;
                     int idx = n.IndexOf('`', StringComparison.Ordinal);
                     if (idx > 0)
                     {
                         n = n.Substring(0, idx);
                     }
                     if (withNamespace)
                     {
                         DumpNamespace(b, Type);
                     }
                 }
                 b.Append(n).Append('<');
             }
             bool atLeastOne = false;
             foreach (var t in SubTypes)
             {
                 if (atLeastOne)
                 {
                     b.Append(',');
                 }
                 else
                 {
                     atLeastOne = true;
                 }
                 t.ToString(b, withNamespace);
             }
             b.Append(isTuple ? ')' : '>');
         }
         else
         {
             var n = CodeWriterExtensions.GetTypeAlias(Type);
             if (n == null)
             {
                 if (withNamespace)
                 {
                     DumpNamespace(b, Type);
                 }
                 n = Type.Name;
             }
             b.Append(n);
         }
     }
     if (Kind.IsNullable())
     {
         b.Append('?');
     }
     return(b);
示例#29
0
 /// <summary>
 /// Fluent function application: this enables a procedural fragment to be inlined in a fluent code.
 /// </summary>
 /// <typeparam name="T">Actual type of the code writer.</typeparam>
 /// <param name="this">This code writer.</param>
 /// <param name="f">Fluent function to apply.</param>
 /// <returns>This code writer to enable fluent syntax.</returns>
 public static T Append <T>(this T @this, Func <T, T> f) where T : ICodeWriter
 {
     Throw.CheckNotNullArgument(f);
     return(f(@this));
 }
示例#30
0
 /// <summary>
 /// Fluent action application: this enables a procedural fragment to be inlined in a fluent code.
 /// </summary>
 /// <typeparam name="T">Actual type of the code writer.</typeparam>
 /// <param name="this">This code writer.</param>
 /// <param name="f">Action to apply to this code writer.</param>
 /// <returns>This code writer to enable fluent syntax.</returns>
 public static T Append <T>(this T @this, Action <T> f) where T : ICodeWriter
 {
     Throw.CheckNotNullArgument(f);
     f(@this);
     return(@this);
 }