2015-09-04 64 views
2

我试图以相当通用的方式构造一些对象。有些对象具有构造函数参数,其他则不具备。传递并执行具有不同参数签名的函数

我想要实现的是返回某种构建函数,如果需要我可以提供构造函数参数。

我知道我可以有可选的参数传递下来,但在我的真实场景中,有几个图层,我厌恶添加可选参数的层次结构。

我不太喜欢部分应用程序/ currying,但我可以在这里使用它,如果是这样,如何?

下面是一些示例代码 - 这不会起作用 - 尝试并解释更多我之后的内容。

public void Main() 
{ 
    dynamic buildClass = ClassBuilder<BaseClass>(true); 
    // ideally I'd like to be able to supply the constructor data 
    // here 
    var theClass = buildClass(???) 

} 

public Func<???, TClass> ClassBuilder<TClass>(bool flag) where TClass : BaseClass 
{ 
    // obviously this won't work since the delegates have different 
    // signatures 
    if (flag) return() => GetClassA(); 
    return (x) => GetClassB(x); 
} 


public object GetClassA() 
{ 
    return new ClassA(); 
} 

public object GetClassB(string param) 
{ 
    return new ClassB(param); 
} 

public class BaseClass {} 

public class ClassA : BaseClass {} 

public class ClassB : BaseClass 
{ 
    private string _param; 
    public ClassB(string param) 
    { 
     _param = param; 
    } 
} 

许多THX

小号

+0

如果你能做到这一点,请张贴您的代码 – netaholic

回答

1

必须使用代码反射来检测构造/方法与你的参数并调用它。

Type type = typeof(YourClass); 
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) }); 
object instance = ctor.Invoke(new object[] { 10 }); 

〜来源:Using C# reflection to call a constructor

或者你有一个类的MethodInfo如果你必须使用方法GetClassX

更多信息

https://msdn.microsoft.com/en-us/library/system.type.getconstructor%28v=vs.110%29.aspx

https://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo.invoke%28v=vs.110%29.aspx

2

到E laboyl @Sylwekqaz,你可以在下面找到类似的东西,而不是只限于BaseClass

public static class Builder 
{ 
    public static T Build<T>(params object[] args) where T : class 
    { 
     var info = typeof(T).GetConstructor(args.Select(arg => arg.GetType()).ToArray()); 
     if (info == null) 
      throw new ArgumentException(@"Can't get constructor :(", "args"); 

     return (T)info.Invoke(args.ToArray()); 
    } 
} 

然后你就可以打电话给你的助洗剂

var a = Builder.Build<ClassA>(); 
var b = Builder.Build<ClassB>(); // need parameterless ctor in ClassB 
var c = Builder.Build<ClassB>("param"); 
+1

这非常好。 –

1

我并不完全按照你的代码示例,但你问有关部分应用和柯里...

最好我发现的方法是创建N个函数,它们从1-N个通用参数中获取,然后让编译器选择一个你想要的。如果你看看我的language-ext项目,我有两个功能,一个叫curry和一个叫par为讨好和部分应用:

Currying source

Partial application source

为了局部应用,这样做:

// Example function 
int AddFour(int a,int b,int c, int d) 
{ 
    return a + b + c + d; 
} 

// This returns a Func<int,int,int> with the first two arguments 10 & 5 auto-provided 
var tenfive = par(AddFour, 10, 5); 

// res = 10 + 5 + 1 + 2 
var res = tenfive(1,2); 

要咖喱,这样做:

// Example function 
int AddFour(int a,int b,int c, int d) 
{ 
    return a + b + c + d; 
} 

// Returns Func<int,Func<int,Func<int,Func<int,int>>>> 
var f = curry(AddFour); 

// res = 10 + 5 + 1 + 2 
var res = f(10)(5)(1)(2); 
相关问题