Передайте экземпляр параметра Class as в конструктор атрибута

Мне нужен экземпляр класса/модели (с целью доступа к нестатическому члену) в пределах моего пользовательского атрибута.

public class LoginModel
{
     [AutoComplete(currentInstance)]  //pass instance of class or CompanyNames
     public string DepartmentName { get; set; }


     public string[] DepartmentNames { get {...} }
}

Есть ли способ сделать это, не используя new() или Reflection.

Ответы

Ответ 1

Это совершенно невозможно. Атрибуты запекаются в метаданные сборки во время компиляции, поэтому говорить о передаче экземпляра класса атрибуту не имеет никакого смысла, потому что экземпляры существуют только во время выполнения.

С другой стороны, атрибуты всегда потребляются отражением, поэтому я предполагаю, что на данный момент вы проверяете наличие этого настраиваемого атрибута в метаданных класса, вы можете использовать экземпляр.

Ответ 2

Невозможный человек, вы не можете передать экземпляр, делегировать, лямбда-выражение в конструктор Атрибута. Некоторые обсуждают это на здесь

Ответ 3

Вы можете использовать примитивы или массивы примитивов в качестве параметров атрибута, это потому, что они должны быть "встроены" компилятором во время компиляции.

Ответ 4

https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx Основанный на MSDN, он полностью не может быть выполнен, если вам нужно передать экземпляр класса для обработки здесь.

Параметры атрибута ограничены постоянными значениями следующие типы: простые типы (bool, byte, char, short, int, long, float и double) string System.Type перечисляет объект (аргумент параметр атрибута объекта типа должен быть постоянным значением одного из вышеупомянутые типы.) Одномерные массивы любого из вышеперечисленных типов

Кроме того, вы могли бы объяснить, почему мы стоим в контексте атрибутов и нуждаемся в получении информации от своего собственного объекта. Это звучит странно, потому что мы часто используем атрибут для более подробной информации об объекте, но не для чтения данных объекта.

Ответ 5

Для доступа к нестационарному члену вам необходимо создать экземпляр класса во время выполнения. У меня есть обходное решение для этого. Если вы хотите использовать экземпляр определенного класса, вы можете создать экземпляр нового экземпляра на основе определенного типа, указанного или представленного как перечисление.

Я использовал Factory Pattern, Strategy Pattern и Reflection для этого. Шаблон стратегии предназначен для реализации различных алгоритмов с обертыванием каждого класса с типом перечисления, в то время как класс Factory должен нести ответственность за регистрацию всех типов реализованных классов и создание подходящего во время выполнения на основе определенного атрибута. Это может быть сложным в начале, но стало очевидно, чтобы получить его позже. Вот пример:

  • Вот все типы проверки, представленные в перечислении

    [Flags]
    public enum AlgorithmTypes
    {
        None = 0,
        All = 1,
        AtLeastOne = 2
    }
    
  • Теперь оберните все их в шаблон стратегии:

    public class NoneValidationMode : RequiredValidationMode
    {
        public NoneValidationMode() { }
        public  override bool IsValid(string properties, object value)
        {
            //validation code here
        }
    }
    
    public class AllValidationMode: RequiredValidationMode
    {
        public   override bool IsValid(string properties,object value)
        {
            //validation code here
        }
    }
    
    public class AtLeastOneValidationMode : RequiredValidationMode
    {
        public  override bool IsValid(string properties, object value)
        {
            //validation code here
        }
    }
    public abstract class RequiredValidationMode
    {
        public abstract bool IsValid(string properties, object value);
    }
    
  • Теперь вот шаблон Factory, который отвечает за создание правильного экземпляра для вас:

    public class AlgorithmStrategyFactory
    {
        private static ArrayList _registeredImplementations;
    
        static AlgorithmStrategyFactory()
        {
            _registeredImplementations = new ArrayList();
            RegisterClass(typeof(NoneValidationMode));
            RegisterClass(typeof(AllValidationMode));
            RegisterClass(typeof(AtLeastOneValidationMode));
        }
        public static void RegisterClass(Type requestStrategyImpl)
        {
            if (!requestStrategyImpl.IsSubclassOf(typeof(RequiredValidationMode)))
                throw new Exception("requestStrategyImpl  must inherit from class RequiredValidationMode");
    
            _registeredImplementations.Add(requestStrategyImpl);
        }
        public static RequiredValidationMode Create(AlgorithmTypes algorithmType)
        {
            // loop thru all registered implementations
            foreach (Type impl in _registeredImplementations)
            {
                // get attributes for this type
                object[] attrlist = impl.GetCustomAttributes(true);
    
                // loop thru all attributes for this class
                foreach (object attr in attrlist)
                {
                    if (attr is AlgorithmAttribute)
                    {
                        if (((AlgorithmAttribute)attr).AlgorithmType.Equals(algorithmType))
                        {
                            return (RequiredValidationMode)System.Activator.CreateInstance(impl);
                        }
                    }
                }
            }
            throw new Exception("Could not find a RequiredValidationMode implementation for this AlgorithmType");
        }
    }
    
  • Теперь атрибут validation можно использовать над классами, конструктор принимает AlgorithmType, который будет указывать позже, какой алгоритм следует выбрать и вызвать.

    [AttributeUsage(AttributeTargets.Class, AllowMultiple =false)]
    public class MyAttribute : ValidationAttribute
    {
        AlgorithmTypes AlgorithmType;
    
        public MyAttribute(AlgorithmTypes algorithm = AlgorithmTypes.None)
        {
            AlgorithmType = algorithm;
        }
    
        public override bool IsValid(object value)
        {
    
            return (AlgorithmStrategyFactory.Create(AlgorithmType)).IsValid(Properties, value);
        }
    }