Могу ли я преобразовать его в строку json вместо того, чтобы использовать отражение в l oop через свойства класса? Есть ли у этого недостатки? - PullRequest
2 голосов
/ 18 июня 2020

Предположим, у меня есть класс, подобный приведенному ниже

class Student
{
public int ID { get; set; }

public string Name { get; set; }
}

Только с еще 10 свойствами. Я хочу l oop через эти свойства. Я могу сделать это через рефлексию, что приведет к снижению производительности. Сериализует его с помощью Newtonsoft JSON и лучше его перебирает?


Edit: Причина, по которой я хочу это сделать, в том, что существует много таких классов. Каждый из этих классов также имеет объект Ienumerable, как показано ниже

public bool Validation
{
public string PropName { get; set; }
public bool IsRequired { get; set; }
public int? MaxLength { get; set; }
public int? MinLength { get; set; }

public void Validate(object propValue)
{... }
}

Я хочу l oop через каждое свойство в классе ученика, принимать значения и передавать их для проверки метода. Но я не хочу использовать отражение. Я не уверен, возможно ли это вообще. Дайте мне знать, если у вас есть какие-нибудь мысли.

1 Ответ

4 голосов
/ 18 июня 2020

Если вас беспокоит снижение производительности отражения, вы можете "кэшировать" его, используя общие c stati c классы и частные поля stati c в них (которые не являются общими) и некоторые маги компиляции c используя деревья выражений . Например (изменил ваш код, чтобы он скомпилировался):

public static class Validator<T>
{
    private static readonly Dictionary<string, Func<T, object>> propGetters;
    static Validator()
    {
        propGetters = 
        typeof(T)
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => p.GetGetMethod() != null)
            .ToDictionary(p => p.Name, p =>
            {
                var par = Expression.Parameter(typeof(T));
                var access = Expression.Property(par, p);
                var lambda = Expression.Lambda<Func<T, object>>(Expression.Convert(access, typeof(object)), par);
                return lambda.Compile();
            });
    }   

    public static bool Validate(T c, IEnumerable<Validation> v)
    {
        return v.All(v => v.Validate(propGetters[v.PropName](c)));
    }
}

class Student
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class Validation
{
    public string PropName { get; set; }
    public bool IsRequired { get; set; }
    public int? MaxLength { get; set; }
    public int? MinLength { get; set; }

    public bool Validate(object propValue)
    { return false; }
}

Что можно использовать следующим образом:

var x = new Student();
var validations = new[]
{
    new Validation
    {
        PropName = "Name",
        IsRequired = true,
        MinLength = 1,
        MaxLength = 10
    }
};
Validator<Student>.Validate(x, validations);

Этот код можно улучшить (например, если IEnumerable<Validation> является коллекцию в самом классе, вы можете переместить код, получив его в другое свойство stati c, и удалить соответствующий параметр Validator.Validate)

...