C# CustomAttributeData класс для атрибута

У меня есть следующий код, расположенный в Swashbuckle.Swagger.IOperationFilter учебный класс.

List<CustomAttributeData> controllerAttributes = apiDescription
    .ActionDescriptor
    .ControllerDescriptor
    .ControllerType
    .CustomAttributes
    .Where(a => a.AttributeType == typeof(SwaggerFileInFormDataAttribute))
    .ToList();

Я успешно получаю коллекцию. Я хочу преобразовать коллекциюList<CustomAttributeData> в коллекцию моего настраиваемого атрибута List<SwaggerFileInFormDataAttribute>.

Я хочу преобразовать System.Reflection.CustomAttributeData класс к моему настраиваемому атрибуту SwaggerFileInFormDataAttribute.


Изменить 1:
вот как мойSwaggerFileInFormDataAttribute атрибут выглядит.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple =false, Inherited =false)]
public class SwaggerFileInFormDataAttribute: Attribute
{
    private ICollection<string> displayNames;

    public SwaggerFileInFormDataAttribute()
    {
        this.DisplayNames = new List<string> { "File" };
    }

    public SwaggerFileInFormDataAttribute(params string[] displayNames)
    {
        this.DisplayNames = displayNames;
    }

    public ICollection<string> DisplayNames
    {
        get
        {
            if (this.displayNames == null)
                return new List<string> { "File" };
            else
                return this.displayNames;
        }
        set => displayNames = value;
    }
}

После успешного преобразования List<CustomAttributeData> к List<SwaggerFileInFormDataAttribute> Я буду использовать свойство, показанное в классе SwaggerFileInFormDataAttribute названный DisplayNames.

2 ответа

Решение

Первое решение:

List<SwaggerFileInFormDataAttribute> customControllerAttributes = apiDescription
    .ActionDescriptor
    .ControllerDescriptor
    .ControllerType
    .CustomAttributes
    .Where(a => a.AttributeType == typeof(SwaggerFileInFormDataAttribute))
    .Select(a =>
    {
        ReadOnlyCollection<CustomAttributeTypedArgument> costuctorArgumentsReadOnlyCollection = (ReadOnlyCollection<CustomAttributeTypedArgument>)a.ConstructorArguments.Select(x => x.Value).FirstOrDefault();

        string[] contructorParams = costuctorArgumentsReadOnlyCollection?.ToArray().Select(x => x.Value.ToString()).ToArray();
        SwaggerFileInFormDataAttribute myCustomAttr = (SwaggerFileInFormDataAttribute)Activator.CreateInstance(a.AttributeType, contructorParams);
        return myCustomAttr;
    })
    .ToList();

Объяснение: Обе переменныеcostuctorArgumentsReadOnlyCollection а также contructorParams можно пропустить, если желаемый атрибут имеет пустой конструктор.

В этом случае достаточно будет только этой строки:
(SwaggerFileInFormDataAttribute)Activator.CreateInstance(a.AttributeType, null);

Второе решение:

Это гораздо более чистое решение. Мы можем полностью пропуститьCustomAttributeData класс в IOperationFilter как это:

List<SwaggerFileInFormDataAttribute> controllerAttributes = apiDescription
    .ActionDescriptor
    .ControllerDescriptor
    .GetCustomAttributes<SwaggerFileInFormDataAttribute>()
    .ToList();

После вашего .Where, добавьте выберите и переведите соответствующим образом. Самым простым было бы создать в своем пользовательском классе конструктор, который принимаетSwaggerFileInFormDataAttributeв качестве параметра и при необходимости сопоставляется с вашим пользовательским классом. Тогда твойSelect было бы:

.Where(a => a.AttributeType == typeof(SwaggerFileInFormDataAttribute))
.Select(a => new CustomAttributeData(a))
.ToList();
Другие вопросы по тегам