Reputation: 628
i really searched in all the covariance questions, and nothing looks like my problem.
I have a user control (this class cant be generic, for obvious reasons), and it looks like this:
class MyUserControl : UserControl
{
private BaseDao<object> _dao;
private AppointmentMapping<object> _mapping;
// I need these 2 generics to type safe the mapping/dao relation
public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping)
{
// These two dont work. even with safe and unsafe casting.
_dao = dao;
_mapping = mapping;
}
}
I already tried to store a delegate for covariance, interfaces and etc. It just dont store the object! How can i achieve this? This is easily achievable with Java.
Upvotes: 2
Views: 444
Reputation: 8005
Try this the following. The idea is to capture the T at usage time and store it in a class that "knows what to do later". Then reference the item in your class via an interface (omitting type information). Later on call the stored value via the interface. That way you don't need to refactor your generic classes to implement certain interfaces.
class MyUserControl : UserControl
{
// hold a reference to the helper - no generics needed here -> "covariant"
private IHelper helper;
// I need this 2 generics to type safe the relation between the mapping and the dao
public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping) {
// "pass <T>" for later usage
this.helper = new HelperImpl<T>(dao, mapping);
}
// use the stored values...
public void doStuff() {
helper.doStuff();
}
// the non generic interface
private interface IHelper
{
void doStuff();
}
// a generic implementation for storing the items *and* using them.
private sealed class HelperImpl<T> : IHelper
{
private readonly BaseDao<T> dao;
private readonly AppointmentMapping<T> mapping;
public HelperImpl(BaseDao<T> dao, AppointmentMapping<T> mapping) {
this.dao = dao;
this.mapping = mapping;
}
public void doStuff() {
this.dao.foo();
this.mapping.foo();
}
}
}
Upvotes: 2
Reputation: 2775
H.alex is right, best thing would be to move the generic bit on a different layer so you can make the class generic and then have generic class members rather than objects. The class must be able to infer the generic type or you'll have to write something like:
public class BaseDao<T>
{
public T Item { get; set; }
}
public class TestClass
{
private BaseDao<object> _dao;
public void RegisterPersistence<T>(BaseDao<T> dao)
{
_dao = Activator.CreateInstance<BaseDao<object>>();
//need to map each member of BaseDao
_dao.Item = dao.Item;
}
}
which is clearly not maintainable as you have to take care of mapping all members on the new instance.
Upvotes: 0
Reputation: 3361
To use covariance and contravariance is necessary a Interface!
Covariance: IInterface<out T>
Contravariance: IInterface<in T>
Check this link for more information: http://weblogs.asp.net/dixin/archive/2009/08/31/understanding-csharp-covariance-and-contravariance-3-samples.aspx
Upvotes: 1
Reputation: 902
This is to the best of my knowledge impossible.
Like Sebastian said, what you can do is have
class MyUserControl : UserControl
{
private object _dao;
private object _mapping;
// I need this 2 generics to type safe the relation between the mapping and the dao
public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping)
{
_dao = dao;
_mapping = mapping;
}
public BaseDao<T> GetDao<T>()
{
return _dao as BaseDao<T>;
}
public AppointmentMapping<T> GetAppointmentMapping<T>()
{
return _mapping as AppointmentMapping<T>;
}
}
Upvotes: 0