如何包装 Func财产

发布于 2024-11-30 19:59:42 字数 879 浏览 3 评论 0原文

这是简化的设置 - 我有 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
}

那么,使用后一种方法是好的丑陋的。

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

This is simplified setup - I have API (I have n o control on the API), which exposes a Func property like this:

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

Usually it's used like this:

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

Similar code is used all over the place (of course the content in {} is different), and I want to add common functionality to all these, I'd like to create a "wrapper" method, which I can use like this:

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

I know I can edit all these calls to look like:

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

But if my common functionality is something like:

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

then, using the latter approach is kind of ugly.

That's why even if it's only for learning purposes, how should my wrapper's method signature look like? And how should I use it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

喜你已久 2024-12-07 19:59:42

如果我理解正确的话,它还应该返回一个 Func,如下所示:

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 不会调用您传递给它的委托。相反,它返回一个委托,当调用该委托时,它将调用您传递的委托。这种延迟执行可能会令人困惑,但我相信这就是您想要的。

If I understand you right, it should also return a Func<dynamic, MyClass>, like this:

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

That's an example with the using statment you wanted.

Note that calling MyWrapperMethod does not call the delegate you pass into it. Instead, it returns a delegate which, when called, will call the delegate you passed. This sort of deferred execution can be confusing, but I believe it's what you want here.

哆啦不做梦 2024-12-07 19:59:42

您可以执行以下操作:

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

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

You could do something like this:

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

Note that it looks like you're using delegate properties to simulate methods. This smells like a very bad architecture to me.

浅语花开 2024-12-07 19:59:42

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

建议一

为您的委托创建不同的签名:

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

There are multiple ways of doing this:

Suggestion One

Creating a different signature for your delegate:

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

Then your method changes like so:

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

And then invoke like so:

 api.FuncProperty(new HelperObject(someDynamic));

Suggestion Two

Create an extension method on dynamic to give you the data you need.

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

And you could then use it like so:

api.FuncProperty = s =>
  {
      var helper = (s as object).CreateHelper();

      return new MyClass();
  };

Suggestion Three

Remove the delegate as a property from your object and change it to a method abstraction:

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

      return helper();
 }

Then you would call like so:

 api.ExecuteFunc(x => 
    {
        return new MyClass();
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文