Передать экземпляр Class в качестве параметра конструктору Attribute - PullRequest
14 голосов
/ 26 ноября 2010

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

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


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

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

Ответы [ 5 ]

14 голосов
/ 26 ноября 2010

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

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

3 голосов
/ 01 декабря 2010

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

2 голосов
/ 26 ноября 2010

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

0 голосов
/ 24 сентября 2017

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

Я использовал для этого Фабричный паттерн, Стратегический паттерн и Технику отражения. Стратегический шаблон должен реализовывать различные алгоритмы с упаковкой каждого класса в тип перечисления, в то время как фабричный класс должен отвечать за регистрацию всех типов реализованных классов и создание подходящего во время выполнения на основе определенного атрибута. Это может быть сложно в начале, однако стало очевидно, что позже. Вот практический пример:

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

    [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");
        }
    }
    
  • Теперь атрибут валидации может использоваться над классами, конструктор принимает 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);
        }
    }    
    
0 голосов
/ 18 октября 2016

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...