There should be no problem in casting to abstract, you can also add Interface definition and have your classes inherit them for example:
public interface IRelated{
IList<InfoBase>Related {get; set;}
}
public class ExtraInfo : InfoBase, IRelated
{
public IList<InfoBase> Related { get; set; }
}
public class OtherInfo:IRelated{
public IList<InfoBase> Related { get; set; }
}
and cast to interface instead class:
ExtraInfo i = new ExtraInfo(){ Id = 5 };
var p = (InfoBase)i;
var q = (IRelated)i;
q.Related.Add(new ExtraInfo());
However I can see other problem in your code: in the Add method you mistype properties:
data.Related.Id
since data.Related returns IList of InfoBase not the InfoBase class itself.
Edit:
You have to be more clear what do you expect to get from the related (or what is Get parameter list).
Edit 2:
here is the Add method code for you:
TData Add<TData>(TData data) where TData:Data
{
var infoBase = data as InfoBase; //or IRelated as in my earlier samples
TData result;
if (infoBase != null)
{
result = Get(data.id, infoBase.Related[0].Id); //you can also use infoBase.Id as first param
}
else
{
result = Get(data.id, null); //whatever you need to pass to the method if there is no related item
}
}
Edit 3:
here's working code:
public class Data
{
public int Id { get; set; }
//...
}
public class InfoData<TInfo> : Data
where TInfo: InfoBase
{
public TInfo Info { get; set; }
//...
}
/* Info classes */
// ABSTRACT
public abstract class InfoBase
{
public int Id { get; set; }
// ...
}
public interface IRelated
{
IList<InfoBase> Related {get; set;}
}
public class ExtraInfo : InfoBase, IRelated
{
public IList<InfoBase> Related { get; set; }
}
public class OtherInfo : InfoBase, IRelated
{
public IList<InfoBase> Related { get; set; }
}
...
class MainClass
{
public static TData Get<TData>(int id, int? related)
where TData: Data
{
Console.WriteLine("id: {0}, related:{1}", id, related);
return (TData)null;
}
public static TData Add<TData>(TData data)
where TData: Data
{
return Get<TData>(data.Id,null);
}
public static TData Add<TData, TInfo>(TData data)
where TData: InfoData<TInfo>
where TInfo: InfoBase
{
var infoBase = data.Info as IRelated;
if (infoBase == null)
return Get<TData>(data.Id, null);
return Get<TData>(data.Id, infoBase.Related[0].Id);
}
public static void Main(string[] args) {
var i = new ExtraInfo {
Id = 5,
Related = new List<InfoBase> { new ExtraInfo { Id = 1 }}
};
var data = new InfoData<ExtraInfo> { Id = 100, Info = i };
var result1 = Add<InfoData<ExtraInfo>, ExtraInfo>(data);
var result2 = Add(data);
}
}
but... this whole code does not look good :)
There are couple possible improvements:
- you can move Add method into the class Data and then override
- you can pass related Id into the add method instead of passing the whole object
- you can re-think the domain and check if you really need so much overloads.