Filipe Carvalho
Filipe Carvalho

Reputation: 628

C# covariance in a non generic class

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

Answers (4)

Sebastian
Sebastian

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

Giorgio Minardi
Giorgio Minardi

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

J. Lennon
J. Lennon

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

h.alex
h.alex

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

Related Questions