【问题标题】:How to pass a generic property as a parameter to a function?如何将泛型属性作为参数传递给函数?
【发布时间】:2008-09-21 08:47:03
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: c# generics


    【解决方案1】:

    你也可以这样写:

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

    【讨论】:

    【解决方案2】:

    您可以使用反射,您可以为 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);
    }
    

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

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

    【讨论】:

      【解决方案3】:

      属性只是方法的语法糖。

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

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

      【讨论】:

      • 这是一个非常好的 KISS 原则。不幸的是,此时我无法使用它:(问题是我正在使用的属性不是我的代码的一部分。编写包装器会增加我此时不想要的开销
      【解决方案4】:

      @Dror 助手,

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

      的函数

      【讨论】:

        【解决方案5】:

        回复:aku 的回答:

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

        【讨论】:

        • 是的,解决方案无论如何都会涉及反射。您可以创建一些有用的包装器,但我更喜欢使用更简单的代码。实践表明,复杂的反射解决方案非常脆弱。
        • Martijn - 我已经回答了你关于创建包装器的问题 - 虽然它是一个足够简单的解决方案,但它不是我需要的
        猜你喜欢
        • 2018-04-02
        • 1970-01-01
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 2017-06-04
        • 2022-11-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多