How can you drop items in a ICollection
without knowing its TSource
? I thought LINQ would be the best route for this, but I cannot figure out how it might be done with Reflection or any other method.
I am trying to implement this in a class that inherits System.Attribute
so generic types are not permitted. And, the returned type information must be the same as the type information received on the value
parameter of MutateValue
. So obviously, generic would be a joy in this case, but is there another solution.
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;
}
}
}
You will see this code will not compile and throws this error:
Error CS1061: 'ICollection' does not contain a definition for 'Take' and no extension method 'Take' accepting a first argument of type 'ICollection' could be found (are you missing a using directive or an assembly reference?)
This class is an extension to the Dado.ComponentModel.Mutations project. Definitions for other Dado.ComponentModel.Mutations
member definitions should be sought there.