2012-02-07 119 views
3

在一箇舊的項目覆蓋的公共屬性,我們使用的是第三方組件,有一些硬編碼信息的屬性的類:派生類

public string ConnectionString 
{ 
    get 
    { 
     string[] fullDbName = new string[5]; 
     fullDbName[0] = "Data Source="; 
     fullDbName[1] = this.dbServer; 
     fullDbName[2] = ";Initial Catalog="; 
     fullDbName[3] = this.FullDbName; 
     fullDbName[4] = ";Integrated Security=SSPI;Pooling=false"; 
     return string.Concat(fullDbName); 
    } 
} 

我需要能夠構建連接串我的自我。所以,我試圖讓一個派生類隱藏了原來的屬性,但它似乎不工作:

public class SqlServerRestorerExstension : SQLServerRestorer 
{ 
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown) 
    { 
     ConnectionString = connectionstring; 
    } 

    public string ConnectionString { get; private set; } 
} 

是否有可能做任何的方式實現這一目標時,我沒有存取權限的第三方碼?

+0

SQLServerRestorer是否實現了其中聲明瞭ConnectionString的任何接口? – 2012-02-07 15:37:48

+0

不,ConnectionString屬性被聲明爲類SQLServerRestorer上的公共屬性。 – peterbf 2012-02-14 07:11:28

回答

5

正如其他人指出的,您可以使用new關鍵字來隱藏基本成員屬性。然而請注意,這不會神奇地將ConnectionString屬性變成多態函數,即如果你有這樣的事情:

public class A 
{ 
    public string CString { get { return "a"; } } 
} 

public class B : A 
{ 
    public new string CString { get { return "b"; }} 
} 

和你這樣做:

A a = new B(); 

Console.WriteLine(a.CString); 

那麼你仍將看到一個「A」打印到控制檯。事實上,new關鍵字只是停止編譯器發出關於隱藏基類成員的警告。它不會在運行時改變代碼的行爲。

你可以嘗試使用Decorator模式幷包裝SQLServerRestorer,但是如果這樣也行不通,恐怕你運氣不好。

+0

是的,這是我正在經歷的行爲:( 我會看看Decorator模式 – peterbf 2012-02-08 07:33:25

+0

我不認爲Decorator模式會有幫助,因爲SQLServerRestorer類用於定義第三個變量第三方代碼 - 因此最初的ConnectionString屬性將會被應用 – peterbf 2012-02-08 08:15:41

+0

@peterbf這就是我所害怕的,否則隱藏屬性的訣竅可能會起作用,你可以嘗試一下像[PostSharp]這樣的面向方面的框架, (http://www.sharpcrafters.com/)或[Afterthought](https://github.com/vc3/Afterthought),它允許您通過MSIL注入修改現有程序集的屬性。 – afrischke 2012-02-08 11:30:44

3

您正在尋找的new關鍵字:

public class SqlServerRestorerExstension : SQLServerRestorer 
{ 
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown) 
    { 
     ConnectionString = connectionstring; 
    } 

    public new string ConnectionString { get; private set; } 
} 
4

您需要指明要「取代」這個屬性,使用new

public new string ConnectionString 
{ 
    get { return "My custom connection string"; } 
} 

很明顯,你可以擴展即使只是使用自動實現的訪問器,也要實現自己的set。與new「版本」文件可以發現here,但具體是:

使用new關鍵字告訴你的定義包含隱藏在基類中定義的編譯器。這是默認行爲。

0

你想override的方法,但似乎你不能:

使用覆蓋劑以調節的方法,屬性,索引器或事件。重寫方法提供了從基類繼承的成員的新實現。覆蓋聲明覆蓋的方法稱爲重寫的基本方法。重寫的基本方法必須與重寫方法具有相同的簽名。

您無法重寫非虛擬或靜態方法。重寫的基本方法必須是虛擬的,抽象的或重寫的。

雖然其他人指出,你可以使用new修改,我不認爲這會有助於你:

它是使用新的和覆蓋同一成員,因爲上一個錯誤這兩個修飾語具有相互排斥的含義。新修飾符創建一個具有相同名稱的新成員,並使原始成員隱藏。 override修飾符擴展了繼承成員的實現。

對我來說,這聽起來像使用基地(第三方)類型的任何代碼將調用舊的屬性 - 這是一個混亂只是等待發生!

+0

這就是在C#中使用'new'修飾符的原因。 – Yuck 2012-02-07 15:40:13

+0

OP真的想替換這個房產。 OP沒有像現在這樣使用'override'。 – 2012-02-07 15:42:07

+0

@ Mr.Disappointment完全正確--OP想要改變他沒有源代碼的對象的行爲。 'new'就可以做到這一點。正如這裏所建議的,他不是想把'override'和'new'結合起來。 – Yuck 2012-02-07 15:43:55