如何将泛型属性作为参数传递给函数?

时间:2020-03-06 14:30:10  来源:igfitidea点击:

我需要编写一个将属性作为参数接收并执行其getter的函数。

如果我需要传递一个函数/委托,我会使用:

delegate RET FunctionDelegate<T, RET>(T t);

void func<T, RET>(FunctionDelegate function, T param, ...)
{
    ...
    return function.Invoke(param);
}

有没有类似的方法来定义属性,以便我可以在函数代码中调用它的getter和/或者setter?

解决方案

属性只是方法的语法糖。

我不认为我们可以修改属性,使其变成"可以调用的吸气剂"的某个实体。

但是,我们可以创建方法GetPropertyValue()并将其作为委托传递给它。

@Dror助手,

恐怕你不能那样做。编译器会生成get_PropertyName和set_PropertyName方法,但是如果不使用Reflection,将无法访问它们。 IMO最好的办法是创建一个函数,该函数接受System.Reflection.ProperyInfo和System.Object参数,并返回propInfo.GetValue(obj,null);

我们可以使用反射,可以为get / set访问器获取MethodInfo对象,并将其称为Invoke方法。

该代码示例假定我们同时具有get和set访问器,并且如果要在生产代码中使用它,则确实必须添加错误处理:

例如,要获取对象obj的属性Foo的值,可以编写:

value = obj.GetType().GetProperty("Foo").GetAccessors()[0].Invoke(obj,null);

设置它:

obj.GetType().GetProperty("Foo").GetAccessors()[1].Invoke(obj,new object[]{value});

因此,我们可以将obj.GetType()。GetProperty(" Foo")。GetAccessors()[0]传递给方法并执行它的Invoke方法。

一种更简单的方法是使用匿名方法(这将在.net 2.0或者更高版本中使用),让我们使用代码示例的稍作修改的版本:

delegate RET FunctionDelegate<T, RET>(T t);

void func<T, RET>(FunctionDelegate<T,RET> function, T param, ...)
{
    ...
    return function(param);
}

对于一个int类型的名为Foo的属性,该属性是SomeClass类的一部分:

SomeClass obj = new SomeClass();
func<SomeClass,int>(delegate(SomeClass o){return o.Foo;},obj);

回复:阿库的答案:

然后,我们必须先获取该属性信息。似乎"使用反射"是对较困难的Cquestions的标准回答,但是反射产生的代码不太难维护。 Dror,为什么不创建一个为我们读取属性的委托?这是一个简单的方法,可能是解决问题的最快,最漂亮的解决方案。

我们还可以编写如下内容:

static void Method<T, U>(this T obj, Expression<Func<T, U>> property)
        {
            var memberExpression = property.Body as MemberExpression;
            //getter
            U code = (U)obj.GetType().GetProperty(memberExpression.Member.Name).GetValue(obj, null);
            //setter
            obj.GetType().GetProperty(memberExpression.Member.Name).SetValue(obj, code, null);
        }

以及调用示例:

DbComputerSet cs = new DbComputerSet();
cs.Method<DbComputerSet, string>(set => set.Code);