2012-02-07 97 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