摆脱函数的论点

时间:2012-11-23 22:26:10

标签: c# f# ironpython dsl

最好用代码解释我的意图。所以现在我有以下代码:

class A, IInterfaceUsedByB
{
}

class B
{
    void func(A someObject)
    {
        func2(someObject, 1);
        func3(someObject, "string");
        func4(someObject, new MyObject());

        var anotherObject = someObject.NewInstance;
        func2(anotherObject, 1);
        .......................
    }
    func2(A someObject, int val);
    func3(A someObject, string val);
    func4(A someObject, C val);
}

func2func3func4确实需要对someObject的引用。我想将此更改为

void func(A someObject)
{
    with(someObject,
            () =>
                {
                    func2(1);
                    func3("string");
                    func4(new MyObject());
                }
        );
    var anotherObject = someObject.NewInstance;
    with(anotherObject,
            () =>
                {
                    func2(1);
                    .......................
                }
        );
}

甚至更好

void func(A someObject)
{
    func2(1);
    func3("string");
    func4(new MyObject());
}

所以我不必拖动这个someObject,但我仍然可以在func2,3,4中使用它。换句话说,就像为特定代码块设置一些上下文对象。我可以使用三种语言中的任何一种(C#,F#或IronPython)。

UPDATE 在理想的解决方案中,B类将独立于A. func*函数仅依赖于由2个方法组成的A的小接口。

UPDATE2 对于不同的函数调用,someObject可以不同。

UPDATE3 我认为只有使用类,接口或扩展方法等语言原语才能做到这一点。我认为使用更多的hackish工具可以实现解决方案,例如属性,反射或F#的计算工作流功能。或者也许是IronPython的一些动态功能。基本上我要做的就是创建一个小型嵌入式DSL。

4 个答案:

答案 0 :(得分:1)

部分功能应用程序可能适合您。

// object for example first param
var objectInstance = new object();

// partial function application
var func2Partial = new Action<int>((i) => func2(objectInstance, i));
func2Partial(5);

如果func2返回了某些内容,那么你需要使用Func&lt;&gt;而不是行动&lt;&gt;

或者,根据我在下面的评论,扩展方法也可以是一个选项。

internal static class IInterfaceUsedByBExtender
{
    internal static void Func2(this IInterfaceUsedByB obj, int value)
    {
    }

}

// caller
someObject.Func2(5);

另一个选项可能是F#中的管道操作符。我有v。基本的F#知识,但我认为你可以定义一个带有两个参数的函数,并使用管道运算符来填充第一个参数的值。如下所示:

let printnums x y = printfn "%A - %A" x y;;

可以通过

调用
4 |> printnums 5;;

哪个输出:

4 - 5

使用func2你会有像

这样的东西
let func2 obj, num = ...;
someObject |> func2 1;;

更多例子:stackoverflow: Piping F# Parameters

我希望这有帮助!

答案 1 :(得分:0)

如果所有这些函数都在一个对象(sameObject)上运行,看起来你应该引入一个类并使它们成为类方法。我不知道someObject是什么类型的,但这是C#中的一个例子:

class Workflow<T>
    where T: class
{
    private readonly T _someObject;

    public Workflow(T someObject)
    {
        _someObject = someObject;
    }


    public void func() 
    {
         func2(1);
         func3("string");
         func4(new MyObject());
    } 

    private void func2(int a) 
    {
        // use _someObject here
    }

    private void func3(string s) 
    {
        // ...
    }
}

// usage
var flow = new Workflow(someObject);
flow.f();

答案 2 :(得分:0)

class A, IInterfaceUsedByB
{ 
}

class B<T> where T : A
{
    private T m_SomeObject;

    public B(T someobject)
    {
        m_Someobject = someobject;
    }
    void func()
    {
        func2(1);
        func3("string");
        func4(new MyObject());
    }
    func2(int val) { //Do whatever with m_SomeObject }
    func3(string val) { //Do whatever with m_SomeObject }
    func4(C val){ //Do whatever with m_SomeObject }
}

答案 3 :(得分:0)

你可以编写一个带A的函数并返回一个func2函数。 例如,如果func2返回类型为void(如果没有,则使用Func&lt; int,ReturnType&gt;):

        Action<int> func2Gen(A someObject)
        {
           return i => Console.WriteLine(i+someObject.ToString());
        }

然后,如果适合,您可以声明

var func2=func2Gen(someObject);

并称之为:

func2(1);