将属性作为参数的通用函数

时间:2013-09-24 13:28:22

标签: c# .net generics reflection

我想编写一个泛型函数,它接受一个对象和该对象的一系列属性。在函数内部,我想选择一个新的匿名对象,它只是传入对象的那些属性。

我想做这样的事情:

public class SimpleClass
{
    public DateTime ADate {get; set;}
    public string StringHere {get; set;}
    public int ANumber {get; set;}
}

var testObj = new SimpleClass();
// set values here on testObj properties
DoStuffHere(testObj, StringHere, ANumber);

我可以将属性作为字符串传递,然后使用反射从传入的对象中获取属性,但我想知道是否有某种方法可以传递属性本身,所以我可以有智能感知和编译时间检查以防止错误的属性名称。我希望我的getNewClass函数可以使用任何类型的对象,这样就是通用的。

编辑:我没有返回一个新的匿名类型。我认为我的功能名称让它听起来如此。我将从指定的testObj列表中内部选择一个新的匿名类型,并从这些属性生成PDF。

3 个答案:

答案 0 :(得分:4)

定义匿名类型实际上非常复杂,尝试使用名称进行操作有点挑战性。基本上你想要的东西已经存在,但是在普通的C#中 - 所以对于一个对象:

var obj = new { testObj.StringHere, testObj.ANumber };

或多个对象:

var projection = from obj in sequence
                 select new { obj.StringHere, obj.ANumber };

这就像你会得到的那样简洁。您可以添加一种采用某种Func<,>的通用方法,但它不会比上面更清晰。

拥有:

是没用的
var obj = SomeMagicMethod(obj, "StringHere", "ANumber");

因为SomeMagicMethod只能有效地返回object - 我们的obj变量很大程度上无法使用。


如果您不需要从该方法返回对象,那么您可以使用以下任一项:

SomeMagicMethod<T>(T value) {
   ...
}
...
SomeMagicMethod(new {testObj.StringHere, testObj.ANumber });

或:

SomeMagicMethod<TFrom, TTo>(TFrom value, Func<TFrom, TTo> selector)
{
    TTo actualVal = selector(value);
    ...
}
...
SomeMagicMethod(testObj, x => new {x.StringHere, x.ANumber });

就个人而言,我认为第一个更容易 - 第二个中的功能是过度杀伤。

您也可以使用反射......

SomeMagicMethod(object obj, params string[] names)
{
    foreach(var name in names) {
       object val = obj.GetType().GetProperty(name).GetValue(obj);
       // ...
    }
}
//...
SomeMagicMethod(testObj, "StringHere", "ANumber");

答案 1 :(得分:0)

你可以将它们作为lambda传递:

GetNewClass (testObj, ()=>StringHere, ()=> ANumber);

并拥有GetNewClass的签名

void GetNewClass (object, Expression<Func<object>> expr0, Expression<Func<object>> expr1);

然后您可以轻松获得该物业。

答案 2 :(得分:0)

您可以使用Linq表达式。

(注意:你可能需要在下面的代码片段中修改一些内容,这是我的首要任务):

public void getNewClass(Object testObj, params MemberExpression Fields[])
{
    foreach(MemberExpression field in Fields)
    {
        // Get the name
        var name = field.Member.Name;

        // get the value
        var member= Expression.Convert(field, typeof(object));
        var lambda= Expression.Lambda<Func<object>>(member);
        var fnc= lambda.Compile();

        var value = fnc();
    }
}

此代码段显示如何获取属性的名称和值。它可以像这样调用:

getClass(someObj, obj => obj.SomeProperty, obj.SomeOtherProperty);