예제 #1
0
        private static ConstructorInfo GetConstructorInfo(Type interfaceType)
        {
            IList <Type> classTypes = (interfaceType.IsInterface || interfaceType.IsAbstract)
                                        ? ImplementationTypes
                                      .Where(type => interfaceType.IsAssignableFrom(type))
                                      .ToArray()
                                        : new[] { interfaceType };

            if (classTypes.Count > 1)
            {
                throw new ArgumentException($"Multiple implementations of type {interfaceType.Name} exists, cannot create a single instance.", nameof(interfaceType));
            }
            if (classTypes.Count == 0)
            {
                throw new ArgumentException($"No implementations of type {interfaceType.Name} exists, cannot create an instance.", nameof(interfaceType));
            }
            var classType = classTypes[0];

            var constructorInfo = classType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null);

            if (constructorInfo == null)
            {
                throw new ArgumentException($"The implementation of type {interfaceType.Name} doesn't have a parameterless constructor. This is required to create an instance.", nameof(interfaceType));
            }

            return(constructorInfo);
        }
예제 #2
0
        internal void SetActive(ImplementationTypeDescriptor implementationType)
        {
            foreach (var type in ImplementationTypes)
            {
                type.IsActive = false;
            }

            ImplementationTypes.Single(x => x.Type == implementationType.Type).IsActive = true;
        }
예제 #3
0
 public void AddDefaultImplementation <TImplementation>(ImplementationConfiguration config) =>
 ImplementationTypes.Add(
     new ImplementationTypeDescriptor
 {
     Type                = typeof(TImplementation),
     IsDefault           = true,
     IsActive            = true,
     Priority            = config.FailoverPriority,
     ExcludeFromFailover = config.ExcludeFromFailover,
 });
예제 #4
0
        private static IList <Delegate> CreateMultipleConstructorDelegates <T>(Type interfaceType)
        {
            var classTypes = ImplementationTypes
                             .Where(type => interfaceType.IsAssignableFrom(type));

            var constructorInfos = classTypes
                                   .Select(classType => classType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null));

            return(constructorInfos
                   .Select(CreateDelegate <T>)
                   .ToList());
        }
예제 #5
0
        public ServiceLocator()
        {
            var locatorType = GetType();

            if (_cachedConstructors.TryGetValue(locatorType, out _constructors))
            {
                return;
            }

            lock (_cacheLock)
            {
                if (_cachedConstructors.TryGetValue(locatorType, out _constructors))
                {
                    return;
                }

                _constructors = new Dictionary <TKey, Func <T> >();
                var interfaceType = typeof(T);

                var foundImplementations = ImplementationTypes.Where(type => interfaceType.IsAssignableFrom(type));
                if (!foundImplementations.Any())
                {
                    throw new ArgumentException($"The type {interfaceType.Name} has no implementations.");
                }

                foreach (var implementationType in foundImplementations)
                {
                    var constructorDelegate = CreateConstructorDelegate(implementationType);
                    var instance            = constructorDelegate();
                    var key = instance.LocatorKey;
                    if (_constructors.ContainsKey(key))
                    {
                        throw new ArgumentException($"Multiple classes are not allowed to return the same LocatorKey: {key}");
                    }

                    _constructors[key] = constructorDelegate;
                }
                _cachedConstructors[locatorType] = _constructors;
            }
        }