2015-09-04 65 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); 
相關問題