【问题标题】:How do I wrap Func<dynamic, MyClass> property如何包装 Func<dynamic, MyClass> 属性
【发布时间】:2011-08-24 05:25:08
【问题描述】:

这是简化的设置 - 我有 API(我无法控制 API),它公开了这样的 Func 属性:

public Func<dynamic, MyClass> FuncProperty { get; set; }

通常是这样使用的:

api.FuncProperty = s =>
   {
      do1();
      do2();
      return new MyClass(); //simplified
   }

到处都在使用类似的代码(当然 {} 中的内容不同),我想为所有这些添加通用功能,我想创建一个“包装器”方法,我可以使用它像这样:

api.FuncProperty = MyWrapperMethod( 
   s =>
   {
      do1();
      do2();
      return new MyClass();
   });

我知道我可以将所有这些调用编辑成如下所示:

api.FuncProperty = s =>
  {
     DoMyCommonFunctionality();
     //... as before
  }

但如果我的常用功能是这样的:

using(var disposable = SetSomeState())
{
   //the stuff which previously was in the lambda
}

那么,使用后一种方法有点难看。

这就是为什么即使只是为了学习目的,我的包装器的方法签名应该是什么样子的?又该如何使用呢?

【问题讨论】:

    标签: c# lambda func


    【解决方案1】:

    如果我没听错的话,它也应该返回一个Func&lt;dynamic, MyClass&gt;,像这样:

    public static Func<dynamic, MyClass> MyWrapperMethod(Func<dynamic, MyClass> func)
    {
        // Validation if you want
        return d =>
        {
            using(var disposable = SetSomeState())
            {
                return func(d);
            }
        };
    }
    

    这是您想要的 using 声明的示例。

    请注意,调用MyWrapperMethod调用您传递给它的委托。相反,它返回一个委托,当被调用时,它将调用您传递的委托。这种延迟执行可能会令人困惑,但我相信这正是您想要的。

    【讨论】:

      【解决方案2】:

      你可以这样做:

      public Func<dynamic, MyClass> MyWrapperMethod(Func<dynamic, MyClass> func)
      {
          if (func == null)
              throw new ArgumentNullException("func");
      
          return s => {
              DoMyCommonFunctionality();
      
              // Execute original function
              return func(s);
          };
      }
      

      请注意,您似乎在使用委托属性来模拟方法。对我来说,这闻起来像是一个非常糟糕的架构。

      【讨论】:

      • 谢谢,这是我需要的。小解释:这不是气味——我用属性来简化。实际上,我使用的是 Nancy (github.com/NancyFx/Nancy/wiki/Documentation),这不是一个属性,而是一个具有已定义路由的索引器,以及每个路由的操作。我想将 NDC 日志记录在每个调用周围。
      • 我明白了,所以这个例子有点误导。
      • 它总结了我需要的东西,我不想深入解释。你回答的正是我需要的:)。再次感谢。顺便说一句,我不介意有人将问题编辑成更清晰的方式。
      【解决方案3】:

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

      建议一

      为您的代表创建不同的签名:

       public Func<HelperObject<dynamic>, MyClass> FuncProperty { get; set; }
      

      然后你的方法改变如下:

       api.FuncProperty = h =>
          {
              //h.Model is the dynamic
              //h.CommonHelperFunction()
              return new MyClass();
          };
      

      然后像这样调用:

       api.FuncProperty(new HelperObject(someDynamic));
      

      建议二

      在动态上创建一个扩展方法,为您提供所需的数据。

      public static MyHelperClass CreateHelper(this object obj)
      {
           return new MyHelperClass();
      }
      

      然后你可以像这样使用它:

      api.FuncProperty = s =>
        {
            var helper = (s as object).CreateHelper();
      
            return new MyClass();
        };
      

      建议三

      将委托作为属性从对象中移除,并将其更改为方法抽象:

       public MyClass ExecuteFunc(Func<dynamic, MyClass> selector)
       {
            Func<MyClass> helper = () =>
               {
                   DoCommonFunctionality();
                   return selector(x.Model);
               };
      
            return helper();
       }
      

      那么你会这样调用:

       api.ExecuteFunc(x => 
          {
              return new MyClass();
          });
      

      【讨论】:

      • 谢谢,但我无法控制 API。
      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2021-11-15
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多