Пример #1
0
        public override void Validate(IErrorReporter errorReporter)
        {
            if (injectedType.HasGenericParameters)
            {
                errorReporter.LogError("Open generic types may not be injected: " + injectedType.FullName);
                return;
            }

            switch (injectedType.Attributes & TypeAttributes.VisibilityMask)
            {
            case TypeAttributes.NestedFamily:
            case TypeAttributes.NestedFamANDAssem:
            case TypeAttributes.NestedPrivate:
            case TypeAttributes.NotPublic:
                // This type is not externally visible and can't be included in a compiled plugin.
                // It can still be loaded reflectively.
                IsVisibleToPlugin = false;
                errorReporter.LogWarning(injectedType.FullName + ": This type is private, and will be loaded reflectively.  Consider making it internal or public.");
                break;
            }

            Key         = CompilerKeys.ForType(injectedType);
            MembersKey  = CompilerKeys.GetMemberKey(injectedType);
            IsSingleton = injectedType.CustomAttributes.Any(Attributes.IsSingletonAttribute);

            var injectableCtors = injectedType
                                  .GetConstructors()
                                  .Where(ctor => ctor.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                  .ToList();

            foreach (var ctor in injectableCtors)
            {
                if (InjectableCtor != null)
                {
                    errorReporter.LogError(string.Format("{0} has more than one injectable constructor.", injectedType.FullName));
                }

                if (!ctor.Attributes.IsVisible())
                {
                    errorReporter.LogError("{0} has an injectable constructor, but it is not accessible.  Consider making it public.");
                }

                InjectableCtor = ctor;
            }

            InjectableProperties = injectedType
                                   .Properties
                                   .Where(p => p.DeclaringType == injectedType)
                                   .Where(p => p.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                   .Select(p => new PropertyInfo(p))
                                   .ToList();

            foreach (var p in InjectableProperties)
            {
                if (p.Setter == null)
                {
                    errorReporter.LogError(string.Format("{0} is marked [Inject] but has no setter.", p.MemberName));
                    continue;
                }

                if (!p.Setter.Attributes.IsVisible())
                {
                    const string msg = "{0}.{1} is marked [Inject], but has no visible setter.  Consider adding a public setter.";
                    errorReporter.LogError(string.Format(msg, injectedType.FullName, p.PropertyName));
                }
            }

            if (InjectableCtor == null)
            {
                if (InjectableProperties.Count == 0 && !IsEntryPoint)
                {
                    errorReporter.LogError("No injectable constructors or properties found on " + injectedType.FullName);
                }

                var defaultCtor = injectedType.GetConstructors().FirstOrDefault(ctor => !ctor.HasParameters);
                if (defaultCtor == null)
                {
                    errorReporter.LogError("Type " + injectedType.FullName + " has no [Inject] constructors and no default constructor.");
                    return;
                }

                InjectableCtor = defaultCtor;
            }

            CtorParams = InjectableCtor.Parameters.Select(p => new InjectMemberInfo(p)).ToList();

            var baseType        = injectedType.BaseType;
            var baseTypeAsmName = baseType.Maybe(type => type.Scope)
                                  .Maybe(scope => scope.Name);

            if (baseType == null ||
                baseTypeAsmName == null ||
                baseTypeAsmName.StartsWith("mscorlib") ||
                baseTypeAsmName.StartsWith("System") ||
                baseTypeAsmName.StartsWith("Microsoft") ||
                baseTypeAsmName.StartsWith("Mono"))
            {
                // We can safely skip types known not to have [Inject] bindings, i.e. types
                // from the BCL, etc.
                BaseTypeKey = null;
            }
            else
            {
                // Otherwise, base types might have [Inject] properties that we'll need
                // to account for.
                BaseTypeKey = Weaver.EnqueueBaseTypeBinding(baseType)
                    ? CompilerKeys.ForType(baseType)
                    : null;
            }
        }
Пример #2
0
        public override void Validate(IErrorReporter errorReporter)
        {
            if (injectedType.HasGenericParameters)
            {
                if (genericInstanceType == null ||
                    genericInstanceType.GenericArguments.Count != injectedType.GenericParameters.Count)
                {
                    errorReporter.LogError("Open generic types may not be injected: " + injectedType.FullName);
                    return;
                }
            }

            if (!injectedType.IsVisible())
            {
                // This type is not externally visible and can't be included in a compiled loader.
                // It can still be loaded reflectively.
                IsVisibleToLoader = false;
                errorReporter.LogWarning(injectedType.FullName + ": This type is private, and will be loaded reflectively.  Consider making it internal or public.");
            }

            Key         = CompilerKeys.ForType(injectedType);
            MembersKey  = CompilerKeys.GetMemberKey(injectedType);
            IsSingleton = injectedType.CustomAttributes.Any(Attributes.IsSingletonAttribute);

            var injectableCtors = injectedType
                                  .GetConstructors()
                                  .Where(ctor => ctor.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                  .ToList();

            foreach (var ctor in injectableCtors)
            {
                if (InjectableCtor != null)
                {
                    errorReporter.LogError(string.Format("{0} has more than one injectable constructor.", injectedType.FullName));
                }

                if (!ctor.IsVisible())
                {
                    errorReporter.LogError(string.Format("{0} has an injectable constructor, but it is not accessible.  Consider making it public.", injectedType.FullName));
                }

                InjectableCtor = ctor;
            }

            InjectableProperties = injectedType
                                   .Properties
                                   .Where(p => p.DeclaringType == injectedType)
                                   .Where(p => p.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                   .Select(p => new PropertyInfo(p))
                                   .ToList();

            foreach (var p in InjectableProperties)
            {
                if (p.Setter == null)
                {
                    errorReporter.LogError(string.Format("{0} is marked [Inject] but has no setter.", p.MemberName));
                    continue;
                }

                if (!p.Setter.IsVisible())
                {
                    const string msg = "{0}.{1} is marked [Inject], but has no visible setter.  Consider adding a public setter.";
                    errorReporter.LogError(string.Format(msg, injectedType.FullName, p.PropertyName));
                }
            }

            if (InjectableCtor == null)
            {
                if (InjectableProperties.Count == 0 && !IsModuleInjectable)
                {
                    errorReporter.LogError("No injectable constructors or properties found on " + injectedType.FullName);
                }

                // XXX ben: this is wrong, I think - entry points with no ctor will still fail.
                var defaultCtor = injectedType.GetConstructors().FirstOrDefault(ctor => !ctor.HasParameters && ctor.IsVisible());
                if (defaultCtor == null && !IsModuleInjectable)
                {
                    errorReporter.LogError("Type " + injectedType.FullName + " has no [Inject] constructors and no default constructor.");
                    return;
                }

                InjectableCtor = defaultCtor;
            }
            // InjectableCtor is null iff this is a value-type entry-point with no default ctor.
            // It's OK, such types never get constructed, only "provided".
            CtorParams = InjectableCtor == null
                ? new List <InjectMemberInfo>()
                : InjectableCtor.Parameters.Select(p => new InjectMemberInfo(p)).ToList();

            var baseType        = injectedType.BaseType;
            var baseTypeAsmName = baseType.Maybe(type => type.Scope)
                                  .Maybe(scope => scope.Name);

            if (baseType == null ||
                baseTypeAsmName == null ||
                baseTypeAsmName.StartsWith("mscorlib") ||
                baseTypeAsmName.StartsWith("System") ||
                baseTypeAsmName.StartsWith("Microsoft") ||
                baseTypeAsmName.StartsWith("Mono"))
            {
                // We can safely skip types known not to have [Inject] bindings, i.e. types
                // from the BCL, etc.
                BaseTypeKey = null;
            }
            else
            {
                // Otherwise, base types might have [Inject] properties that we'll need
                // to account for.
                BaseTypeKey = Weaver.EnqueueBaseTypeBinding(baseType)
                    ? CompilerKeys.ForType(baseType)
                    : null;
            }
        }