I wrote ASP.NET pages which will manage forms. They're based on the following base class.
public abstract class FormPageBase<TInterface, TModel> : Page, IKeywordProvider
where TModel:ActiveRecordBase<MasterForm>, TInterface, new()
where TInterface:IMasterForm
{
public TInterface FormData { get; set; }
}
And a sample SubClass is here:
public partial class PersonalDataFormPage : FormPageBase<IPersonalDataForm, PersonalDataForm>, IHasFormData<IPersonalDataForm>, IHasContact
{
}
Below I have a usercontrol on the page which I want to "consume" the "FormData" from the page so that it can read/write to it.
I then, have a more "common" user control that I want to have operate on the base Interface of all my form subclasses... IMasterForm
But when the usercontrol tries casting Page.FormData (having tried to cast page to IHasFormData<IMasterForm>
it tells me that the page is IHasFormData<IFormSubclass>
even though I have a constraint on the IFormSubclass that says it is also IMasterForm
Is there anyway that i can cast from the generic subclass to the generic superclass or is this "covariance" and a C# 4.0 thing?
public abstract class FormControlBase<T> : UserControl, IKeywordProvider
where T:IMasterForm
{
protected T FormData { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//This cast is failing when my common control's T does not exactly match
// the T of the Page.. even though the common controls TInterface is a base interface to the
//pages TInterface
FormData = ((IHasFormData<T>) Page).FormData;
if (!IsPostBack)
{
PopulateBaseListData();
BindDataToControls();
}
}
protected abstract void PopulateBaseListData();
protected abstract void BindDataToControls();
public abstract void SaveControlsToData();
#region IKeywordProvider
public List<IKeyword> GetKeywords(string categoryName)
{
if(!(Page is IKeywordProvider ))
throw new InvalidOperationException("Page is not IKeywordProvider");
return ((IKeywordProvider) Page).GetKeywords(categoryName);
}
#endregion
}