[英]Passing and executing functions with different parameter signatures
I am trying to construct some objects in a reasonably generic way. 我正在尝试以合理的通用方式构造一些对象。 Some of the objects have constructor params, others don't.
有些对象具有构造函数参数,而另一些则没有。
What I am trying to achieve is to return some kind of builder function to which I can supply the constructor param if required. 我试图实现的是返回某种生成器函数,如果需要的话,我可以向其提供构造器参数。
I know I could have optional params passed down, but in my real scenario, there are several layers and I'm loathed to add optional params down the hierarchy. 我知道我可以传递可选的参数,但是在我的实际场景中,有多层结构,我不愿意在层次结构中添加可选的参数。
I'm not too up on partial application/currying, but could I use that here and if so, how? 我不太关注部分应用程序/ currying,但是我可以在这里使用它吗?如果可以,如何使用?
Here's a bit of sample code - which won't work - to try and explain a bit more what I'm after. 这里有一些示例代码-无法正常工作-尝试解释一下我要做什么。
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;
}
}
Many thx 多谢
S 小号
To elaborate @Sylwekqaz you could have something like below, and not restrict yourself for type of BaseClass
. 要详细说明@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());
}
}
And then you can call your builder as 然后您可以将您的构建者称为
var a = Builder.Build<ClassA>();
var b = Builder.Build<ClassB>(); // need parameterless ctor in ClassB
var c = Builder.Build<ClassB>("param");
You must use code reflection to detect constructor/method with you parameters and invoke it. 您必须使用代码反射来检测带有参数的构造函数/方法并调用它。
Type type = typeof(YourClass);
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) });
object instance = ctor.Invoke(new object[] { 10 });
~source: Using C# reflection to call a constructor 〜source: 使用C#反射调用构造函数
alternatively you have a class MethodInfo if you must use methods GetClassX 或者,如果必须使用方法GetClassX,则有一个MethodInfo类
More info 更多信息
https://msdn.microsoft.com/en-us/library/system.type.getconstructor%28v=vs.110%29.aspx 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 https://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo.invoke%28v=vs.110%29.aspx
I don't entirely follow your code example, but you ask about partial-application and currying... 我不完全遵循您的代码示例,但是您询问部分应用程序和currying ...
The best way I've found is to just create N functions that take from 1-N generic parameters, then let the compiler pick the one you want. 我发现最好的方法是只创建从1-N个通用参数中提取的N个函数,然后让编译器选择所需的函数。 If you take a look at my language-ext project I have two functions, one called
curry
and one called par
for currying and partial application: 如果您看一下我的language-ext项目,我有两个函数,一个叫做
curry
,另一个叫做par
用于currying和部分应用:
Partial application source 部分应用程序源
To partially apply, do this: 要部分申请,请执行以下操作:
// 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);
To curry, do this: 要咖喱,请执行以下操作:
// 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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.