2013-11-03 55 views
2

是否有可能檢查某個類型是否具有無參數構造函數,以便投射它並調用一個需要帶有無參數構造函數的方法並使用: new()約束?如何將對象轉換爲具有公共無參數構造函數以尊重:new()約束?

只能檢查作爲公共無參數的類型,因爲回答here是不夠的,因爲它不允許調用目標方法。

的目標是讓下面的邏輯,其中IInteresting對象不實現一個公共的無參數的構造函數,需要調用Save1之前轉換:

public interface IInteresting { } 

    public void Save<T>(T o) { 
     var oc = o as (new()); /* Pseudo implementation */ 
     if (oc != null) { 
      this.Save1(oc); 
     } 
     else { 
      var oi = o as IInteresting; 
      if (oi != null) { 
       this.Save2(oi); 
      } 
     } 
    } 

    private void Save1<T>(T o) where T : new() { 
     //Stuff 
    } 

    private void Save2<T>(IInteresting o) { 
     //Stuff to convert o to a DTO object with a public parameterless constructor, then call Save1(T o) 
    } 

當然,如果我能Save1Save2份額相同的簽名,將解決問題,但我無法找到一種方式來做到這一點,因爲以下將無法編譯(在Routine,Save將調用第一次實現,而不是第二次):

public void Routine<T>(T o) { 
     var oi = o as IInteresting; 
     if (oi != null) { 
      this.Save(oi); 
     } 
    } 

    private void Save<T>(T o) where T : new() { 
     //Stuff 
    } 

    private void Save<T>(IInteresting o) { 
     //Stuff to convert o to a DTO object with a public parameterless constructor, then call Save(T o) 
    } 
+1

「僅僅是不夠的,因爲它不允許調用目標方法。」 - 實際上,它會的。 ['ConstructorInfo'](http://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo.aspx)包含['Invoke'方法](http://msdn.microsoft.com/zh-cn/ -us /庫/ 6ycw1y17.aspx)。 –

+0

只需使用反射?但首先,重新考慮你的設計。 –

+2

你的Save1 方法裏面有什麼? – sh1ng

回答

1

根據你的意見,我想你有一個未知類型的對象,你想傳遞給一個泛型函數,該函數要求傳遞對象是泛型類型參數,它必須有一個無參數構造函數。因此,暫時,我們可以假設你的問題的函數Save1<T>(T)是那個函數,不是你寫的,不可能被改變。

解決的辦法是通過使用反射來撥打電話:

+0

哇,這確實會這樣做,雖然我希望有更多的開箱即可實現這一點。 –

+1

@ErwinMayer:作爲泛型總是 - 除非你使用反射 - 必須在編譯時解決,而只有在運行時才知道你的類型,恐怕沒有其他可行的方法。你可以添加到這個解決方案中的唯一簡單的簡化就是使用一個通用的類,它自己調用基於非泛型方法調用的泛型方法 - 這樣,你可以跳過'GetMethod'步驟(它基於字符串 - 方法的名稱,因此不用編譯器檢查),而是使用'typeof(MyCallerType <>)。MakeGenericType(o.GetType())'。 –

0

另一個可能的解決方案,取決於你在裏面做什麼private void Save<T>(T o) where T : new()是使用ICloneable接口。或引入你的(正如我已經說過,這取決於Save的內容):

interface IConstructible 
{ 
    object Construct(); 
} 

而且有:

private void Save1<T>(T o) where T : ICloneable { 

當然這只是一種變通方法 - O. R. Mapper's answer給出了唯一的直接的解決方案。

0
using System.Reflection; 


public static class Generics { 
public static void T0<T> (T obj) where T : new() { 
    Console.WriteLine ("{0} {1}", obj, obj.GetType()); 
} 

public static void T1<T> (T obj) { 
    MethodInfo mi = GenericMethodInfo (typeof (Generics), "T0", typeof (T)); 
    mi.Invoke (null, new object[] { obj }); 
} 

public static MethodInfo GenericMethodInfo (Type classType, string methodName, Type genericType) { 
    return classType.GetMethod (methodName).MakeGenericMethod (genericType); 
} 
} 


Generics.T0 (123); 
Generics.T1 (123); 
// Impossible.. Generics.T0 ("12345"); 
Generics.T1 ("12345"); 
+0

最好的答案以及代碼都有一些解釋。請考慮添加一些上下文。 – Chris

相關問題