FxCop не может проанализировать сборку - PullRequest
0 голосов
/ 16 ноября 2011

У меня проблема с некоторыми сборками в моем анализе FxCop. Большинство сборок из нашего проекта работают нормально, за исключением тех, которые для Api. FxCop просто прекращает анализировать их после 135 сообщений с исключением.

Это детали исключения, которые я получаю.

При чтении модуля произошла следующая ошибка 'TenForce.Execution.Api2.Implementation': не удалось разрешить член ссылка: [TenForce.Execution.Api2.Implementation, Version = 1.0.0.0, Culture = нейтрально, PublicKeyToken = нуль] TenForce.Execution.Api2.Implementation.Helpers.IdGenerator 1<type parameter.T>+Wrapper 1 :: Object.

Я позаботился о том, чтобы все необходимые сборки были вместе и являются частью проекта, но я не знаю, как решить эту проблему. Кто-нибудь сталкивался с этим раньше?

  • FxCop 10.0
  • Visual Studio 2010
  • .NET Framework 4
  • TeamCity Test Server

EDIT Добавление исходного кода для класса, вызывающего проблему:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Collections.ObjectModel;

namespace TenForce.Execution.Api2.Implementation.Helpers
{
    /// <summary>
    /// <para>This class is responsible for generating the various Ids for the Ts.</para>
    /// </summary>
    public static class IdGenerator<T> where T : class, IEquatable<T>, new()
    {
        /// <summary>
        /// Wraps underlying object. Requires object to have int Id property.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class Wrapper<T> : IEquatable<Wrapper<T>>
        {
            private PropertyInfo piId;

            /// <summary>
            /// Wrapper constructor
            /// </summary>
            /// <param name="instance"></param>
            public Wrapper(T instance)
            {
                Object = instance;
                Created = DateTime.Now;
                foreach (var pi in instance.GetType().GetProperties())
                {
                    if (pi.Name.Equals("id", StringComparison.OrdinalIgnoreCase))
                    {
                        piId = pi;
                    }
                }

                if (piId == null)
                {
                    var fullName = instance.GetType().FullName;
                    throw new TypeInitializationException(fullName,
                        new Exception(string.Format("{0} is not compatible with IdGenerator. It requires int Id property to be present", fullName)));
                }
            }

            /// <summary>
            /// Gets or sets wrapped instance Id
            /// </summary>
            public int Id
            {
                get
                {
                    return (int)piId.GetValue(Object, null);
                }
                set
                {
                    piId.SetValue(Object, value, null);
                }
            }

            /// <summary>
            /// Creation date
            /// </summary>
            public DateTime Created;

            /// <summary>
            /// Wrapped instance
            /// </summary>
            public T Object;

            /// <summary>
            /// Implements IEquatable interface
            /// </summary>
            /// <param name="other"></param>
            /// <returns></returns>
            public bool Equals(Wrapper<T> other)
            {
                return Object.Equals(other.Object);
            }
        }

        #region Private Fields

        private static Wrapper<T>[] _mWrappers = new Wrapper<T>[10];
        private static readonly object MPadLock = new object();

        #endregion

        #region Public Members

        /// <summary>
        /// <para>Generates a new Id for the T and assigns it to the T.</para>
        /// </summary>
        /// <param name="obj">The T that needs a new Id generated.</param>
        /// <remarks>The T will be stored inside the generator to keep track of the Id and availability.</remarks>
        public static void GenerateId(T obj)
        {
            lock (MPadLock)
            {
                // Search the array for an empty spot or an expired T.
                int index = Array.FindIndex(_mWrappers, s => s == null || DateTime.Now.Subtract(s.Created).Minutes > 10);

                var wrapper = new Wrapper<T>(obj);

                // If we found such a spot, store the new T in that location,
                // If we did not find such a spot, expand the array and the T at the end.
                if (index > -1) _mWrappers[index] = wrapper;
                else
                {
                    Array.Resize(ref _mWrappers, _mWrappers.Length + 1);
                    _mWrappers[_mWrappers.Length - 1] = wrapper;
                }

                // Always update the Id of the T entity with the negative index of the entity's location.
                wrapper.Id = CalculateId(Array.IndexOf(_mWrappers, wrapper));
            }
        }

        /// <summary>
        /// <para>Releases the Id generated for the T and releases the location that was held by the T.</para>
        /// </summary>
        /// <param name="obj">The T that needs to be released.</param>
        /// <remarks>The T will be removed from the generator and it's Id will be reset to zero !!!</remarks>
        public static void ReleaseId(T obj)
        {
            lock (MPadLock)
            {
                var wrapper = new Wrapper<T>(obj);
                if (wrapper.Id >= 0) return;
                int index = Array.IndexOf(_mWrappers, wrapper);
                Array.Clear(_mWrappers, index, 1);
                wrapper.Id = 0;
            }
        }

        /// <summary>
        /// <para>Fetches the specified T from the IdGenerator.</para>
        /// </summary>
        /// <param name="id">The unique identifier of the T.</param>
        /// <returns>The T with the matching Id or the default instance if not found.</returns>
        public static T Fetch(int id)
        {
            lock (MPadLock)
            {
                var found = Array.Find(_mWrappers, s => s != null && s.Id == id);
                return found == null ? new T() : found.Object;
            }
        }

        /// <summary>
        /// <para>Updates the matching T entity inside the Generator with the new one.</para>
        /// </summary>
        /// <param name="obj">The T that needs to be updated.</param>
        public static void Update(T obj)
        {
            lock (MPadLock)
            {
                int index = Array.IndexOf(_mWrappers, obj);
                if (index == -1) return;
                var wrapped = new Wrapper<T>(obj);
                _mWrappers[index] = wrapped;
                wrapped.Id = CalculateId(index);
                wrapped.Created = DateTime.Now;
            }
        }

        /// <summary>
        /// <para>Retrieves all the Ts currently available in the application.</para>
        /// </summary>
        /// <returns>An enumerable collection containing all the T entities.</returns>
        public static IEnumerable<T> ListAll()
        {
            lock (MPadLock)
            {
                return new ReadOnlyCollection<T>(_mWrappers.Select(s => s == null ? null : s.Object).Where(o => o != null).ToList());
            }
        }

        #endregion

        #region Private Members

        /// <summary>
        /// <para>Calculates the negative id for an entity based upon the zero-based index.</para>
        /// </summary>
        /// <param name="index">The zero-based index of the entity who's Id needs to be calculated.</param>
        /// <returns>The new Id for the entity.</returns>
        private static int CalculateId(int index)
        {
            return (index * -1) - 1;
        }
        #endregion
    }
}

Ответы [ 2 ]

3 голосов
/ 16 ноября 2011

Существует несколько известных проблем, которые вызывают проблемы такого рода: https://connect.microsoft.com/VisualStudio/feedback/details/469754/code-analysis-fails-on-specific-conditions-involving-a-generic-class-containing-an-interface и https://connect.microsoft.com/VisualStudio/feedback/details/520967/code-analyze-brokes-while-loading-interface-from-a-separate-module-file-in-an-indirectly-referenced-assembly. Если ни один из этих способов не подходит, не могли бы вы предоставить следующую информацию:

  1. Является ли TenForce.Execution.Api2.Implementation.Helpers пространством имен или типом?
  2. Является ли IdGenerator <> классом или интерфейсом?
  3. Является ли IdGenerator <>. Wrapper <> класс или интерфейс?

После добавления исходного кода к вопросу ...

Проблема возникает из-за того, что оба IdGenerator<T> и вложенный класс Wrapped<T> использует одно и то же имя параметра типа "T".Для этого компилятор C # сгенерировал предупреждение ( CS0693 ), которое вы, очевидно, проигнорировали.Если вы измените имя параметра типа во вложенном классе, FxCop должен иметь возможность правильно анализировать класс (и дать вам знать довольно большое количество проблем, которые в нем содержатся;).

Кстати, я бы оченьНастоятельно рекомендуем рассматривать предупреждения компилятора как ошибки, если вы удаленно заинтересованы в качестве кода, что, вероятно, так и есть, если вы используете FxCop.Зачем добавлять дополнительный инструмент скрининга, прежде чем использовать все преимущества того, что вы уже используете?

1 голос
/ 16 ноября 2011

Просто убедитесь, что сборка GAC или присутствует в той же папке, что и сборка, которую вы анализируете.

Sidenote: Возможно, вы захотите опустить фактическое имя сборки / пространства имен / имени метода. Просто чтобы быть в безопасности и держаться подальше от неприятностей. Если вы понимаете о чем я :) :) 1006 *

...