使用类属性来限制函数参数值

时间:2016-05-26 21:07:08

标签: c# function parameters enums

简单的课程:

public class myTest
{
    public class Person
    {
        public Int32 Id { get; set; }
        public String Fname { get; set; }
        public string Lname { get; set; }
    }

    public enum EPerson
    {
        Id=0,
        Fname=1,
        Lname=2
    }

    public static void Get(EPerson SearchBy, dynamic Value)
    {
        var Sql = "select from dbo.bobo where " + SearchBy.ToString() + "='" + Value + "'";

    }

    public static void testget()
    {
        Get(EPerson.Fname, "Bob");
    }
}

IntelliSense适用于此。我的Get方法显示所有三个枚举值,供我选择一个。

不是在Get方法中使用枚举,而是如何通过查询Person属性来做同样的事情,从而消除了Enum用于IntelliSense目的的需要?

4 个答案:

答案 0 :(得分:3)

您可以使用lambda-expression来使用intellisense等进行编译类型检查。

但是,您只能实际接受lambda表达式的特定子集,并且不能对其进行编译时检查。

private static Person GetPerson(Expression<Func<Person, object>> selectorExpression)
{
    var body = selectorExpression.Body as UnaryExpression;
    var operand = body.Operand as BinaryExpression;
    var left = operand.Left as MemberExpression;
    var right = operand.Right as ConstantExpression;

    string propertyName = left.Member.Name;
    object value = right.Value;

    return /* get person where "propertyName" == "value" here */
}

现在你可以像这样调用GetPerson:

var person = GetPerson(p => p.Name == "Fred");

请注意,lambda表达式必须与p => p.Property == constantValue形式完全相同。

另请注意:我没有在GetPerson中执行任何错误检查,因此错误的格式会导致它在运行时崩溃。

答案 1 :(得分:2)

您可以使用以下功能使用Reflection:

private List<String> GetProperties ( Type Model )
{
    var props = new List<MemberInfo> ( Model.GetFields ( BindingFlags.Public | BindingFlags.Instance ) );
    props.AddRange ( Model.GetFields ( BindingFlags.NonPublic | BindingFlags.Instance ) );
    props.AddRange ( Model.GetProperties ( BindingFlags.Public | BindingFlags.Instance ) );
    props.AddRange ( Model.GetProperties ( BindingFlags.NonPublic | BindingFlags.Instance ) );

    var names = new List<String> ( );
    props.ForEach ( prop => names.Add ( prop.Name ) );

    return names;
}

将获得所有课程&#39;字段和属性(the difference)可以是公共的或私有的。

它做什么

  1. 它将模型类型作为参数;
  2. 获取所有属性和字段,并将它们添加到列表中;
  3. 将其作为List<String>返回,其中包含所有属性&#39;和领域&#39;名。
  4. 用法

    获取属性和字段名称:

    var props = GetProperties ( typeof ( Person ) )
    

    然后检查传递的参数是否在列表中:

    if ( props.Contains ( SearchBy ) )
    {
        // Do something...
    }
    

答案 2 :(得分:1)

如果要限制方法在编译时中接收的参数,您将始终必须有一个枚举(至少到目前为止,C#无法获取属性列表在编译时。

但是,如果您可以在运行时中限制输入,则可以使用反射来获取属性列表并检查输入以查看是否应返回或抛出异常/返回错误代码。值得一提的是,反射所以请确保你确实需要它或性能不是问题。

另一方面,如果您需要编译时检查,但希望能够查询对象的属性值(而不是数据库,因为您的Get方法似乎在做),您可以使用枚举,并使用反射通过枚举获取属性值,这样您就知道要获取哪个属性的值,但我建议在这种情况下使用Dictionary来存储值并使用使用枚举的类型安全属性,这样你就拥有了“两全其美”。你仍然有枚举,但如果你需要编译时检查它是你能做的最好的。 以下是此方法的示例实现(没有完整性检查):

public class myTest
{
    public class Person
    {
        protected Dictionary<string, object> _properties;

        public Person()
        {
            _properties = new Dictionary<string, object>();
        }

        public Int32 Id 
        { 
            get 
            { 
                return (int)_properties[EPerson.Id];
            } 
            set
            {
                _properties[EPerson.Id] = value;
            }
        }
        public String Fname 
        { 
            get 
            { 
                return _properties[EPerson.FName] as String;
            } 
            set
            {
                _properties[EPerson.FName] = value;
            }
        }
        public string Lname
        { 
            get 
            { 
                return _properties[EPerson.LName] as String;
            } 
            set
            {
                _properties[EPerson.LName] = value;
            }
        }
    }

    public enum EPerson
    {
        Id = 0,
        Fname = 1,
        Lname = 2
    }

    public static void Get(EPerson SearchBy, dynamic Value)
    {
        var Sql = "select from dbo.bobo where " + SearchBy.ToString() + "='" + Value + "'";
    }

    public static void testget()
    {
        Get(EPerson.Fname, "Bob");
    }
}

答案 3 :(得分:0)

听起来你想制作一个方法,它允许你找到具有匹配的id,名字或姓氏的Person个实例,而不使用enum来指定搜索类型。

有几种方法可以做到这一点:

  1. 每种搜索类型的单独方法。如果你想通过ID找到它们,那么你可以使用GetPersonById(int)' method. By first name would be GetPersonByFName(string)'。
  2. 使用默认参数。您的方法签名将是public Person GetPerson(int? id = null, string fName = null, string lName = null)。在该方法中,您将使用非null参数进行搜索。如果all都为null,那么您将返回完整的对象列表或抛出异常(确保指定方法在summary标记中的工作方式)。
  3. 与#2类似,但以Person为唯一参数。用户需要创建新的Person实例才能进行搜索。
  4. bool参数指示要与Value中的值进行比较的列。不建议这样做。