Yes. There are multiple ways of doing this, and this is just one option:
You can make your page implement some custom interface that exposes a method called "GetContext" or something, and it returns your specific information. Then your control can simply request the page and cast:
var myContextPage = this.Page as IMyContextGetter;
if(myContextPage != null)
var myContext = myContextPage.GetContext();
public new MyPage Page {get return (MyPage)Page; set;}'
You can't override the property because it returns a different type... but you can redefine it.
You don't need covariance in this example, since it is relatively simple. All you're doing is inheriting the base object Page from MyPage. Any Control that you want to return MyPage instead of Page needs to redefine the Page property of the Control
It sounds like what you want is return type covariance. C# does not support return type covariance.
Return type covariance is where you override a base class method that returns a less-specific type with one that returns a more specific type:
abstract class Enclosure
{
public abstract Animal Contents();
}
class Aquarium : Enclosure
{
public override Fish Contents() { ... }
}
This is safe because consumers of Contents via Enclosure expect an Animal, and Aquarium promises to not only fulfill that requirement, but moreover, to make a more strict promise: that the animal is always a fish.
This kind of covariance is not supported in C#, and is unlikely to ever be supported. It is not supported by the CLR. (It is supported by C++, and by the C++/CLI implementation on the CLR; it does so by generating magical helper methods of the sort I suggest below.)
(Some languages support formal parameter type contravariance as well -- that you can override a method that takes a Fish with a method that takes an Animal. Again, the contract is fulfilled; the base class requires that any Fish be handled, and the derived class promises to not only handle fish, but any animal. Similarly, C# and the CLR do not support formal parameter type contravariance.)
The way you can work around this limitation is to do something like:
abstract class Enclosure
{
protected abstract Animal GetContents();
public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
protected override Animal GetContents() { return this.Contents(); }
public new Fish Contents() { ... }
}
Now you get both the benefits of overriding a virtual method, and getting stronger typing when using something of compile-time type Aquarium.
class R {
public int A { get; set; }
}
class R1: R {
public int B { get; set; }
}
class A
{
public R X { get; set; }
}
class B : A
{
private R1 _x;
public new R1 X { get => _x; set { ((A)this).X = value; _x = value; } }
}
The following code now builds successfully (without giving: error CS0508: 'Tiger.GetFood()': return type must be 'Food' to match overridden member 'Animal.GetFood()')
class Food { }
class Meat : Food { }
abstract class Animal {
public abstract Food GetFood();
}
class Tiger : Animal {
public override Meat GetFood() => default;
}
class Program {
static void Main() => new Tiger();
}