FxCop не может проанализировать сборку
У меня проблема с некоторыми сборками из моего анализа FxCop. Большинство сборок из нашего проекта работают нормально, за исключением тех, что для Api. FxCop просто перестает анализировать их после 135 сообщений, за исключением.
Это детали исключения, которые я получаю.
При чтении модуля "TenForce.Execution.Api2.Implementation" возникла следующая ошибка: не удалось разрешить ссылку на элемент: [TenForce.Execution.Api2.Implementation, Version=1.0.0.0, Culture= нейтральный, PublicKeyToken = null] TenForce.Execution.Api2.Implementation.Helpers.IdGenerator
1<type parameter.T>+Wrapper
1:: Object.
Я позаботился о том, чтобы все необходимые сборки были вместе и являлись частью проекта, но я не знаю, как решить эту проблему. Кто-нибудь сталкивался с этим раньше?
- FxCop 10.0
- Visual Studio 2010
- .NET Framework 4
- Тестовый сервер TeamCity
РЕДАКТИРОВАТЬ Добавление исходного кода для класса, который вызывает проблему:
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 ответа
Существует несколько известных проблем, вызывающих такие проблемы: 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 while-loading-interface-from-a-separate-module-file- in- сборка с косвенной ссылкой. Если ни один из них не подходит, не могли бы вы предоставить следующую информацию:
- Является ли TenForce.Execution.Api2.Implementation.Helpers пространством имен или типом?
- Является ли IdGenerator<> классом или интерфейсом?
- Является ли IdGenerator<>.Wrapper<> классом или интерфейсом?
После добавления исходного кода к вопросу...
Проблема возникает потому, что оба IdGenerator<T>
и вложенные Wrapped<T>
Класс использует то же имя параметра типа "T". Компилятор C# сгенерировал для этого предупреждение ( CS0693), которое вы, очевидно, проигнорировали. Если вы измените имя параметра типа во вложенном классе, FxCop сможет правильно проанализировать класс (и сообщить вам о довольно большом количестве проблем, которые в нем содержатся;).
Между прочим, я бы настоятельно рекомендовал рассматривать предупреждения компилятора как ошибки, если вы удаленно заинтересованы в качестве кода, что, вероятно, так и есть, если вы используете FxCop. Зачем добавлять дополнительный инструмент скрининга, прежде чем использовать все преимущества того, что вы уже используете?
Просто убедитесь, что сборка GAC или присутствует в той же папке, что и сборка, которую вы анализируете.
Sidenote: вы можете не указывать фактическое имя сборки / пространства имен / имени метода. Просто чтобы быть в безопасности и держаться подальше от неприятностей. Если вы понимаете, о чем я:) *