Click here to Skip to main content
15,891,529 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am having a really bad time with the following code (simplified version of what is in RaptorDB):
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace genericview
{
    public class Iapi // api class 
    {
        public int I;
    }
    public class vbase // view base type
    {
        public string Name;
    }

    public delegate void MapFunc<V>(Iapi i, V doc);
    public class View<T> : vbase // generic view
    {
        public MapFunc<T> Mapper;
    }

    public class A // base type 
    {
        public int I;
    }

    public class B : A // a subclass
    {
        public int J;
    }

    public class vhandler // view handler
    {
        public vbase view;

        public void insert<T>(T doc) // where the magic should be
        {
            Iapi api = new Iapi();

            View<T> v = (View<T>)view; // exception here the second time round

            v.Mapper(api, doc);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            View<A> va = new View<A>();

            va.Name = "a handler";
            va.Mapper = (api, d) =>
            {
                api.I = d.I;
            };

            vhandler vh = new vhandler();
            vh.view = va;

            A a = new A();
            a.I = 10;
            vh.insert(a); // call the insert -> ok

            B b= new B();
            b.I = 100;
            vh.insert(b); // error when calling here
        }
    }
}

Now the problem is that the second call with a subclass of A is not recognized and an exception is raised of an invalid cast from View to a View<A>.

Any clue how to get this fixed or somehow call the v.Mapper with a derived type of A (namely B)?
Posted

 
Share this answer
 
v4
Comments
Mehdi Gholam 8-May-14 13:42pm    
The mapper definition is defined elsewhere out of my control.
I think this is a case where you need to use contravariance in the MapFunc delegate:
C#
public delegate void MapFunc<in V>(Iapi i, V doc);

If I understand this correctly, this says that the MapFunc can take any type that is V or derived from V.

Disclaimer: I haven't needed to use this in anything I've written.
 
Share this answer
 
v4
Comments
Mehdi Gholam 8-May-14 13:41pm    
The editor does not accept this (I'm using .net 4)
Matt T Heffron 8-May-14 13:44pm    
Sorry I typoed. See edit.
The problem is in
SQL
public class vhandler // view handler
{
    public vbase view;

It should be
SQL
public class vhandler<T> // view handler
{
    public View<T> view;
 
Share this answer
 
v2
Comments
Mehdi Gholam 9-May-14 10:16am    
I can't do that because I have a Dictionary of these and you can't have a Dictionary string, vhandler of T

Actually I have found a solution by using dynamic (the first real world case I have seen where it is actually needed, kudus to Anders Hejlsberg).
Bernhard Hiller 12-May-14 2:18am    
Such a Dictionary is not possible with the classes of the framework proper. Perhaps a custom implementation could be possible (I did not try).
But true: in some cases, that odd "dynamic" is a usable work-around (had to use it when writing a wrapper for several versions of a third-party component defined in several PIAs).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900