Как вы можете бросить предметы в ICollection
, не зная его TSource
?Я думал, что LINQ будет лучшим путем для этого, но я не могу понять, как это можно сделать с помощью Reflection или любого другого метода.
Я пытаюсь реализовать это в классе, который наследует System.Attribute
, такой общийтипы не допускаются.И возвращаемая информация о типе должна совпадать с информацией о типе, полученной для параметра value
в MutateValue
.Очевидно, что в этом случае generic будет радостью, но есть другое решение.
using System;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace Dado.ComponentModel.DataMutations
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ApplyMaxLengthStackAttribute : MutationAttribute
{
private int _maxLength = -1;
public object Mutate(object value, int maxLength, IMutationContext context = null)
{
_maxLength = maxLength;
return Mutate(value, context);
}
protected override object MutateValue(object value, IMutationContext context)
{
if (value != null) {
if (
value is string valueAsString &&
(
_maxLength > -1 || TryGetStringLengthAttributeValue(context, out _maxLength)
) &&
valueAsString.Length > _maxLength
) {
value = valueAsString.Substring(0, _maxLength);
}
else if (
value is ICollection valueAsCollection &&
(
_maxLength > -1 || TryGetMaxLengthAttributeValue(context, out _maxLength)
) &&
valueAsCollection.Count > _maxLength
) {
// Error CS1061
value = valueAsCollection.Take(_maxLength);
}
}
_maxLength = -1;
return value;
}
private bool TryGetStringLengthAttributeValue(IMutationContext context, out int maxLength)
{
var attribute = context?.Attributes.OfType<StringLengthAttribute>().FirstOrDefault();
if (attribute != null) {
maxLength = attribute.MaximumLength;
return true;
}
return TryGetMaxLengthAttributeValue(context, out maxLength);
}
private bool TryGetMaxLengthAttributeValue(IMutationContext context, out int maxLength)
{
var attribute = context?.Attributes.OfType<MaxLengthAttribute>().FirstOrDefault();
if (attribute != null) {
maxLength = attribute.Length;
return true;
}
maxLength = -1;
return false;
}
}
}
Вы увидите, что этот код не скомпилируется и выдает эту ошибку:
ОшибкаCS1061: «ICollection» не содержит определения для «Take», и метод расширения «Take», принимающий первый аргумент типа «ICollection», не найден (отсутствует директива using или ссылка на сборку?)
Этот класс является расширением проекта Dado.ComponentModel.Mutations .Определения для других Dado.ComponentModel.Mutations
определений членов следует искать там.