C# 如何将通用属性作为参数传递给函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/110562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:19:18  来源:igfitidea点击:

How to pass a generic property as a parameter to a function?

提问by Dror Helper

I need to write a function that receives a property as a parameter and execute its getter.

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

If I needed to pass a function/delegate I would have used:

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

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

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

Is there a similar way to define a property so that I could invoke it's getter and/or setter in the function code?

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

采纳答案by Nir

You can use reflection, you can get a MethodInfo object for the get/set accessors and call it's Invoke method.

您可以使用反射,您可以为 get/set 访问器获取 MethodInfo 对象并调用它的 Invoke 方法。

The code example assumes you have both a get and set accessors and you really have to add error handling if you want to use this in production code:

代码示例假设您同时拥有 get 和 set 访问器,如果您想在生产代码中使用它,您确实必须添加错误处理:

For example to get the value of property Foo of object obj you can write:

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

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

to set it:

设置它:

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

So you can pass obj.GetType().GetProperty("Foo").GetAccessors()[0] to your method and execute it's Invoke method.

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

an easier way is to use anonymous methods (this will work in .net 2.0 or later), let's use a slightly modified version of your code example:

更简单的方法是使用匿名方法(这适用于 .net 2.0 或更高版本),让我们使用代码示例的稍微修改版本:

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

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

for a property named Foo of type int that is part of a class SomeClass:

对于作为类 SomeClass 一部分的 int 类型的名为 Foo 的属性:

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

回答by Martijn

Properties are simply syntactic sugar for methods.

属性只是方法的语法糖。

I don't think you can modify a property such that it becomes some entity "whose getter you can call".

我不认为您可以修改一个属性,使其成为某个“您可以调用其 getter”的实体。

You can however create a method GetPropertyValue() and pass that around as if it were a delegate.

但是,您可以创建一个方法 GetPropertyValue() 并将其作为委托传递。

回答by aku

@Dror Helper,

@Dror 助手,

I'm afraid you can't do it that way. Compiler generates get_PropertyName and set_PropertyName methods but they are not accessible without using Reflection. IMO best you can do is create function that takes System.Reflection.ProperyInfoand System.Objectparams and returns propInfo.GetValue(obj, null);

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

回答by Martijn

Re: aku's answer:

回复:阿库的回答:

Then you have to obtain that property info first. It seems "use reflection" is the standard answer to the harder C# questions, but reflection yields not-so-pretty hard-to-maintain code. Dror, why not just create a delegate that reads the property for you? It's a simple one-liner and is probably the quickest and prettiest solution to your problem.

然后您必须首先获取该属性信息。似乎“使用反射”是更难的 C# 问题的标准答案,但反射产生的代码不太难维护。Dror,为什么不创建一个为您读取属性的委托?这是一个简单的单线,可能是解决您问题的最快和最漂亮的解决方案。

回答by Bartosz Pierzchlewicz

You can also write something like:

你也可以这样写:

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

and example of invocation:

和调用示例:

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