protected virtual Syntax Validate()
 {
     Required.Select(acceptor => TokenOf(acceptor)).Count();
     return(this);
 }
        /// <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);
                }
        }
Пример #3
0
 public bool IsRequired(PropertyInfo pi)
 {
     return(Required.Select(p => p.ToLower()).Contains(pi.Name.ToLower()));
 }