【问题标题】:Pass instance of Class as parameter to Attribute constructor将 Class 的实例作为参数传递给 Attribute 构造函数
【发布时间】:2017-09-24 15:44:50
【问题描述】:

我需要自定义属性中的类/模型实例(用于访问非静态成员)。

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


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

有没有办法在不使用new() 或反射的情况下做到这一点。

【问题讨论】:

    标签: c# .net asp.net asp.net-mvc attributes


    【解决方案1】:

    这完全不可能。属性在编译时被烘焙到程序集的元数据中,因此谈论将类的实例传递给属性没有任何意义,因为实例仅在运行时存在。

    另一方面,属性总是被反射消耗掉,所以我猜现在你正在检查类元数据上是否存在这个自定义属性,你可以使用实例。

    【讨论】:

    • 有没有办法将数据从属性传递到类实例或方法? (例如,属性可以进行身份​​验证并将经过身份验证的用户传递给方法吗?)
    • 这是完全的限制,是迄今为止我遇到的最大的 c#/.NET 限制之一。非常失望。
    【解决方案2】:

    您只能使用原语或原语数组作为属性参数,这是因为它们需要在编译时由编译器“内联”。

    【讨论】:

      【解决方案3】:

      不可能,你不能将实例、委托、lambda表达式传递给属性的构造函数。有人在here 讨论它

      【讨论】:

        【解决方案4】:

        https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx 基于MSDN,这里如果需要传递一个类的实例来处理是完全做不到的。

        属性参数仅限于 以下类型:简单类型(bool、byte、char、short、int、long、 浮点数和双精度数)字符串 System.Type 枚举对象(参数 类型对象的属性参数必须是其中之一的常量值 上述类型。)上述任何类型的一维数组

        此外,您能否解释一下为什么我们站在属性上下文中并且需要从它们自己的对象中获取信息。这听起来很奇怪,因为我们经常使用 Attribute 来解释有关对象的更多信息,而不是读取对象数据。

        【讨论】:

          【解决方案5】:

          为了访问非静态成员,您需要在运行时实例化一个类。我有一个解决方法。如果您想使用特定类的实例,您可以设法根据列出或表示为枚举的特定类型实例化一个新实例。

          我使用工厂模式、策略模式和反射技术来做到这一点。策略模式是用枚举类型包装每个类来实现不同的算法,而工厂类应该负责注册所有类型的实现类,并根据定义的属性在运行时创建合适的类。一开始可能很复杂,但后来变得很明显。这是一个实际的例子:

          • 这里是枚举中表示的所有验证类型

            [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);
            }
            
          • 现在这里是负责为您创建正确实例的工厂模式:

            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);
                }
            }    
            

          【讨论】:

            猜你喜欢
            • 2013-12-12
            • 2019-09-29
            • 2011-06-28
            • 2017-05-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-10
            • 1970-01-01
            相关资源
            最近更新 更多