peterbf
peterbf

Reputation: 229

Override a public property from a derived class

In an old project we are using a third party assembly with a class that has a property with some hardcoded information:

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);
    }
}

I need to be able to construct the connection string my self. So I have tried to make a derived class that hides the original property, but it does not seem to work:

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; }
}

Is it possible do achive this in any way when I don't have acces to the third party code?

Upvotes: 8

Views: 30069

Answers (4)

afrischke
afrischke

Reputation: 3866

As others have pointed out you can use the new keyword to hide the base member property. Note however that this doesn't magically turn the ConnectionString property into a polymorphic function, i.e. if you have something like this:

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

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

and you do this:

A a = new B();

Console.WriteLine(a.CString);

Then you will still see an "a" printed to the console. In fact the new keyword just stops the compiler from issuing a warning regarding the hiding of the member of the base class. It doesn't change the behavior of the code at runtime.

You can try to use a Decorator pattern and wrap the SQLServerRestorer, but if that doesn't work either, you are out of luck I am afraid.

Upvotes: 16

Grant Thomas
Grant Thomas

Reputation: 45083

You will need to indicate that you want to 'replace' this property, using new:

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

Obviously you can extend that to implement your own set, even if just to utilise auto-implemented accessors. Documentation on 'versioning' with new can be found here, but specifically:

Using the new keyword tells the compiler that your definition hides the definition contained in the base class. This is the default behavior.

Upvotes: 4

Daren Thomas
Daren Thomas

Reputation: 70324

You want to override the method, but it seems you can't:

Use the override modifier to modify a method, a property, an indexer, or an event. An override method provides a new implementation of a member inherited from a base class. The method overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method.

You cannot override a non-virtual or static method. The overridden base method must be virtual, abstract, or override.

Although others point out that you can use the new modifier, I don't think that will serve you well:

It is an error to use both new and override on the same member because the two modifiers have mutually exclusive meanings. The new modifier creates a new member with the same name and causes the original member to become hidden. The override modifier extends the implementation for an inherited member.

To me, that sounds like any code using the base (3rd party) type will invoke the old property - this is a mess just waiting to happen!

Upvotes: 0

Yuck
Yuck

Reputation: 50845

You're looking for the new keyword:

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; }
}

Upvotes: 3

Related Questions