2011-11-05 94 views
1

我有一個帶有2個構造函數的公共類:默認(不帶參數),它是內部的,不同的是公共的。 默認構造函數使用一些默認值調用另一個構造函數。如何防止C#編譯器刪除內部構造函數

我使用反射調用內部構造函數,所以它不會在靜態組件中的任何位置使用(僅通過反射)。

當我做了反思電話,我得到:

System.MissingMethodException 
    Message=No parameterless constructor defined for this object. 

我知道兩種解決方法的:

  1. 使構造公共(但我不希望這樣的用戶裝配使用它)。
  2. 從一些公共方法調用構造函數(我有很多這樣的類,所以我不想寫很多這個醜陋的無用代碼)。

對這個問題有什麼更好的解決辦法?

值得一提的是,如果默認的構造函數是公共的,我不會得到這個異常。

謝謝,

波阿斯。

+4

C#編譯器不會刪除代碼。使用ildasm.exe來說服你自己。 –

+1

向我們顯示導致此異常的代碼。你在反射調用中提供了正確的'BindingFlags'嗎? – AakashM

+0

謝謝,我不知道ildasm。我可以在那裏找到默認的構造函數,但我仍然得到一個MissingMethodException。如果它是公開的,我不明白。 – brickner

回答

7

構造函數未被刪除,可能在搜索構造函數時應指定標記BindingFlag.NonPublic

class xxx 
    { 
     private xxx() : 
      this(10) 
     { 
     } 

     public xxx(int value) 
     { 
      Console.WriteLine(value); 
     } 
    } 

    static void Main(string[] args) 
    { 
     Activator.CreateInstance(typeof(xxx), true); 
     Console.ReadLine(); 
    } 

Activator.CreateInstance有一個布爾值:如果你想調用非公共構造函數,你可以指定一個過載。

public static Object CreateInstance(
    Type type, 
    bool nonPublic 
) 

Activator.CreateInstance(類型,TRUE)會調用構造兩個如果是公共或私人\內部\保護。

+0

謝謝。確實如此。我有其他這樣的類與公共默認構造函數。我試圖設置(BindingFlags.NonPublic | BindingFlags.Public),但它只能找到NonPublic的。 – brickner

+1

Activator.CreateInstance(type,true)將調用構造函數,如果它是public或non-public。 –

+0

謝謝,這個作品! – brickner

3

C#編譯器確實不是爲您刪除任何構造函數。在Reflector中打開程序集,我相信你會看到你創建的構造函數。

我認爲用於查找構造函數的反射代碼更可能不包括BindingFlags.NonPublic。示例代碼,以顯示它如何可以工作:

using System; 
using System.Reflection; 

class Foo 
{ 
    internal Foo() 
    { 
     Console.WriteLine("Foo constructor"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var ctor = typeof(Foo).GetConstructor 
      (BindingFlags.NonPublic | 
      BindingFlags.Public | 
      BindingFlags.Instance, 
      binder: null, 
      types: new Type[0], 
      modifiers: null); 
     ctor.Invoke(null); 
    } 
} 

編輯:要通過綁定標誌來Activator.CreateInstance,您需要使用不同的過載,像這樣:

Activator.CreateInstance(typeof(Foo),         
         BindingFlags.NonPublic | 
         BindingFlags.Public | 
         BindingFlags.Instance, 
         binder: null, 
         args: null, 
         culture: null); 

(或者你可以使用如註釋中所述CreateInstance(type, true)

+0

謝謝。但是,當我使用Activator.CreateInstance(類型,BindingFlags.NonPublic | BindingFlags.Public)時,它只能找到NonPublic,並且找不到具有public類型的公共構造函數。 – brickner

+0

@brickner:我相信你實際上只是調用了錯誤的Activator.CreateInstance重載,並且它試圖將綁定標誌作爲參數傳遞。示例... –

+0

Activator.CreateInstance(type,true)起作用。 – brickner