Open BenBtg opened 4 years ago
Have you done any profiling to see why it's taking so much time?
You could also pass a predicate to AutoRegister to exclude anything in that assembly, and/or update IsIgnoredAssembly to ignore it (would be nice to add a public collection property that would let you add to that ignored assembly list).
Does it seem like a bad practice to do auto registrations in general?
Just wanted to add something to this. I was hacking the current TinyIOC.cs file with an older version of the file as reference that was working and found that by replacing registration region with the below snippet and updating the AutoRegisterInternal function with the older version of the function it no longer autoregisters the all the xf assemblys and seems to work.
I haven't had a chance to investigate why yet the main difference seems to be how it handles the ignoreDuplicateImplementations within the registration.
This is probably a classic case of me fuxing something (fixing one thing and breaking 20 other things in the process) but It might help you guys pin point the issue with XF.
Updated Code
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
///
/// If more than one class implements an interface then only one implementation will be registered
/// although no error will be thrown.
/// </summary>
public void AutoRegister()
{
AutoRegisterInternal(new Assembly[] { this.GetType().Assembly() }, true, null);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
/// Types will only be registered if they pass the supplied registration predicate.
///
/// If more than one class implements an interface then only one implementation will be registered
/// although no error will be thrown.
/// </summary>
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered</param>
public void AutoRegister(Func<Type, bool> registrationPredicate)
{
AutoRegisterInternal(new Assembly[] { this.GetType().Assembly() }, true, registrationPredicate);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
/// </summary>
/// <param name="ignoreDuplicateImplementations">Whether to ignore duplicate implementations of an interface/base class. False=throw an exception</param>
/// <exception cref="TinyIoCAutoRegistrationException"/>
public void AutoRegister(bool ignoreDuplicateImplementations)
{
AutoRegisterInternal(new Assembly[] { this.GetType().Assembly() }, ignoreDuplicateImplementations, null);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
/// Types will only be registered if they pass the supplied registration predicate.
/// </summary>
/// <param name="ignoreDuplicateImplementations">Whether to ignore duplicate implementations of an interface/base class. False=throw an exception</param>
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered</param>
/// <exception cref="TinyIoCAutoRegistrationException"/>
public void AutoRegister(bool ignoreDuplicateImplementations, Func<Type, bool> registrationPredicate)
{
AutoRegisterInternal(new Assembly[] { this.GetType().Assembly() }, ignoreDuplicateImplementations, registrationPredicate);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
///
/// If more than one class implements an interface then only one implementation will be registered
/// although no error will be thrown.
/// </summary>
/// <param name="assemblies">Assemblies to process</param>
public void AutoRegister(IEnumerable<Assembly> assemblies)
{
AutoRegisterInternal(assemblies, true, null);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
/// Types will only be registered if they pass the supplied registration predicate.
///
/// If more than one class implements an interface then only one implementation will be registered
/// although no error will be thrown.
/// </summary>
/// <param name="assemblies">Assemblies to process</param>
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered</param>
public void AutoRegister(IEnumerable<Assembly> assemblies, Func<Type, bool> registrationPredicate)
{
AutoRegisterInternal(assemblies, true, registrationPredicate);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
/// </summary>
/// <param name="assemblies">Assemblies to process</param>
/// <param name="ignoreDuplicateImplementations">Whether to ignore duplicate implementations of an interface/base class. False=throw an exception</param>
/// <exception cref="TinyIoCAutoRegistrationException"/>
public void AutoRegister(IEnumerable<Assembly> assemblies, bool ignoreDuplicateImplementations)
{
AutoRegisterInternal(assemblies, ignoreDuplicateImplementations, null);
}
/// <summary>
/// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
/// Types will only be registered if they pass the supplied registration predicate.
/// </summary>
/// <param name="assemblies">Assemblies to process</param>
/// <param name="ignoreDuplicateImplementations">Whether to ignore duplicate implementations of an interface/base class. False=throw an exception</param>
/// <param name="registrationPredicate">Predicate to determine if a particular type should be registered</param>
/// <exception cref="TinyIoCAutoRegistrationException"/>
public void AutoRegister(IEnumerable<Assembly> assemblies, bool ignoreDuplicateImplementations, Func<Type, bool> registrationPredicate)
{
AutoRegisterInternal(assemblies, ignoreDuplicateImplementations, registrationPredicate);
}
/// <summary>
/// Creates/replaces a container class registration with default options.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType)
{
return RegisterInternal(registerType, string.Empty, GetDefaultObjectFactory(registerType, registerType));
}
/// <summary>
/// Creates/replaces a named container class registration with default options.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, string name)
{
return RegisterInternal(registerType, name, GetDefaultObjectFactory(registerType, registerType));
}
/// <summary>
/// Creates/replaces a container class registration with a given implementation and default options.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="registerImplementation">Type to instantiate that implements RegisterType</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Type registerImplementation)
{
return this.RegisterInternal(registerType, string.Empty, GetDefaultObjectFactory(registerType, registerImplementation));
}
/// <summary>
/// Creates/replaces a named container class registration with a given implementation and default options.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="registerImplementation">Type to instantiate that implements RegisterType</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Type registerImplementation, string name)
{
return this.RegisterInternal(registerType, name, GetDefaultObjectFactory(registerType, registerImplementation));
}
/// <summary>
/// Creates/replaces a container class registration with a specific, strong referenced, instance.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="instance">Instance of RegisterType to register</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, object instance)
{
return RegisterInternal(registerType, string.Empty, new InstanceFactory(registerType, registerType, instance));
}
/// <summary>
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="instance">Instance of RegisterType to register</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, object instance, string name)
{
return RegisterInternal(registerType, name, new InstanceFactory(registerType, registerType, instance));
}
/// <summary>
/// Creates/replaces a container class registration with a specific, strong referenced, instance.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="registerImplementation">Type of instance to register that implements RegisterType</param>
/// <param name="instance">Instance of RegisterImplementation to register</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Type registerImplementation, object instance)
{
return RegisterInternal(registerType, string.Empty, new InstanceFactory(registerType, registerImplementation, instance));
}
/// <summary>
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="registerImplementation">Type of instance to register that implements RegisterType</param>
/// <param name="instance">Instance of RegisterImplementation to register</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Type registerImplementation, object instance, string name)
{
return RegisterInternal(registerType, name, new InstanceFactory(registerType, registerImplementation, instance));
}
/// <summary>
/// Creates/replaces a container class registration with a user specified factory
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="factory">Factory/lambda that returns an instance of RegisterType</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Func<TinyIoCContainer, NamedParameterOverloads, object> factory)
{
return RegisterInternal(registerType, string.Empty, new DelegateFactory(registerType, factory));
}
/// <summary>
/// Creates/replaces a container class registration with a user specified factory
/// </summary>
/// <param name="registerType">Type to register</param>
/// <param name="factory">Factory/lambda that returns an instance of RegisterType</param>
/// <param name="name">Name of registation</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register(Type registerType, Func<TinyIoCContainer, NamedParameterOverloads, object> factory, string name)
{
return RegisterInternal(registerType, name, new DelegateFactory(registerType, factory));
}
/// <summary>
/// Creates/replaces a container class registration with default options.
/// </summary>
/// <typeparam name="RegisterImplementation">Type to register</typeparam>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>()
where RegisterType : class
{
return this.Register(typeof(RegisterType));
}
/// <summary>
/// Creates/replaces a named container class registration with default options.
/// </summary>
/// <typeparam name="RegisterImplementation">Type to register</typeparam>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>(string name)
where RegisterType : class
{
return this.Register(typeof(RegisterType), name);
}
/// <summary>
/// Creates/replaces a container class registration with a given implementation and default options.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <typeparam name="RegisterImplementation">Type to instantiate that implements RegisterType</typeparam>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType, RegisterImplementation>()
where RegisterType : class
where RegisterImplementation : class, RegisterType
{
return this.Register(typeof(RegisterType), typeof(RegisterImplementation));
}
/// <summary>
/// Creates/replaces a named container class registration with a given implementation and default options.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <typeparam name="RegisterImplementation">Type to instantiate that implements RegisterType</typeparam>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType, RegisterImplementation>(string name)
where RegisterType : class
where RegisterImplementation : class, RegisterType
{
return this.Register(typeof(RegisterType), typeof(RegisterImplementation), name);
}
/// <summary>
/// Creates/replaces a container class registration with a specific, strong referenced, instance.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <param name="instance">Instance of RegisterType to register</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>(RegisterType instance)
where RegisterType : class
{
return this.Register(typeof(RegisterType), instance);
}
/// <summary>
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <param name="instance">Instance of RegisterType to register</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>(RegisterType instance, string name)
where RegisterType : class
{
return this.Register(typeof(RegisterType), instance, name);
}
/// <summary>
/// Creates/replaces a container class registration with a specific, strong referenced, instance.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <typeparam name="RegisterImplementation">Type of instance to register that implements RegisterType</typeparam>
/// <param name="instance">Instance of RegisterImplementation to register</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType, RegisterImplementation>(RegisterImplementation instance)
where RegisterType : class
where RegisterImplementation : class, RegisterType
{
return this.Register(typeof(RegisterType), typeof(RegisterImplementation), instance);
}
/// <summary>
/// Creates/replaces a named container class registration with a specific, strong referenced, instance.
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <typeparam name="RegisterImplementation">Type of instance to register that implements RegisterType</typeparam>
/// <param name="instance">Instance of RegisterImplementation to register</param>
/// <param name="name">Name of registration</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType, RegisterImplementation>(RegisterImplementation instance, string name)
where RegisterType : class
where RegisterImplementation : class, RegisterType
{
return this.Register(typeof(RegisterType), typeof(RegisterImplementation), instance, name);
}
/// <summary>
/// Creates/replaces a container class registration with a user specified factory
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <param name="factory">Factory/lambda that returns an instance of RegisterType</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>(Func<TinyIoCContainer, NamedParameterOverloads, RegisterType> factory)
where RegisterType : class
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
return this.Register(typeof(RegisterType), (c, o) => factory(c, o));
}
/// <summary>
/// Creates/replaces a named container class registration with a user specified factory
/// </summary>
/// <typeparam name="RegisterType">Type to register</typeparam>
/// <param name="factory">Factory/lambda that returns an instance of RegisterType</param>
/// <param name="name">Name of registation</param>
/// <returns>RegisterOptions for fluent API</returns>
public RegisterOptions Register<RegisterType>(Func<TinyIoCContainer, NamedParameterOverloads, RegisterType> factory, string name)
where RegisterType : class
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
return this.Register(typeof(RegisterType), (c, o) => factory(c, o), name);
}
/// <summary>
/// Register multiple implementations of a type.
///
/// Internally this registers each implementation using the full name of the class as its registration name.
/// </summary>
/// <typeparam name="RegisterType">Type that each implementation implements</typeparam>
/// <param name="implementationTypes">Types that implement RegisterType</param>
/// <returns>MultiRegisterOptions for the fluent API</returns>
public MultiRegisterOptions RegisterMultiple<RegisterType>(IEnumerable<Type> implementationTypes)
{
return RegisterMultiple(typeof(RegisterType), implementationTypes);
}
/// <summary>
/// Register multiple implementations of a type.
///
/// Internally this registers each implementation using the full name of the class as its registration name.
/// </summary>
/// <param name="registrationType">Type that each implementation implements</param>
/// <param name="implementationTypes">Types that implement RegisterType</param>
/// <returns>MultiRegisterOptions for the fluent API</returns>
public MultiRegisterOptions RegisterMultiple(Type registrationType, IEnumerable<Type> implementationTypes)
{
if (implementationTypes == null)
throw new ArgumentNullException("types", "types is null.");
foreach (var type in implementationTypes)
if (!registrationType.IsAssignableFrom(type))
throw new ArgumentException(String.Format("types: The type {0} is not assignable from {1}", registrationType.FullName, type.FullName));
if (implementationTypes.Count() != implementationTypes.Distinct().Count())
{
var queryForDuplicatedTypes = from i in implementationTypes
group i by i
into j
where j.Count() > 1
select j.Key.FullName;
var fullNamesOfDuplicatedTypes = string.Join(",\n", queryForDuplicatedTypes.ToArray());
var multipleRegMessage = string.Format("types: The same implementation type cannot be specified multiple times for {0}\n\n{1}", registrationType.FullName, fullNamesOfDuplicatedTypes);
throw new ArgumentException(multipleRegMessage);
}
var registerOptions = new List<RegisterOptions>();
foreach (var type in implementationTypes)
{
registerOptions.Add(Register(registrationType, type, type.FullName));
}
return new MultiRegisterOptions(registerOptions);
}
#endregion
private void AutoRegisterInternal(IEnumerable
var concreteTypes = from type in types
where (type.IsClass() == true) && (type.IsAbstract() == false) && (type != this.GetType() && (type.DeclaringType != this.GetType()) && (!type.IsGenericTypeDefinition()))
select type;
foreach (var type in concreteTypes)
{
try
{
RegisterInternal(type, string.Empty, GetDefaultObjectFactory(type, type));
}
catch (MethodAccessException)
{
// Ignore methods we can't access - added for Silverlight
}
}
var abstractInterfaceTypes = from type in types
where ((type.IsInterface() == true || type.IsAbstract() == true) && (type.DeclaringType != this.GetType()) && (!type.IsGenericTypeDefinition()))
select type;
foreach (var type in abstractInterfaceTypes)
{
var implementations = from implementationType in concreteTypes
where implementationType.GetInterfaces().Contains(type) || implementationType.BaseType() == type
select implementationType;
if (!ignoreDuplicateImplementations && implementations.Count() > 1)
throw new TinyIoCAutoRegistrationException(type, implementations);
var firstImplementation = implementations.FirstOrDefault();
if (firstImplementation != null)
{
try
{
RegisterInternal(type, string.Empty, GetDefaultObjectFactory(type, firstImplementation));
}
catch (MethodAccessException)
{
// Ignore methods we can't access - added for Silverlight
}
}
}
}
}
AutoRegister takes ages (over 10 seconds to complete as it seems to register over 10,000 types. For example see AutoRegister