1

I want an Adapter like function. The parent class want DataTable, while its derived class may pass in anything. I'm now setting the data type to object and then cast it. But I do not think this is pretty.

class Parent
{
    protected void Add(DataTable dt) { ... }        // the real business logics
    public virtual void AddRaw(object anything) {}
}

class Child1 : Parent
{
    public override void AddRaw(object anything)
    {
        MyTable1 t = (MyTable1) anything;

        // pseudo code
        DataTable dt = new DataTable();
        foreach(row r in t)
        {
            dt.AddRow(r);
        }

        this.Add(dt);
    }
}

class Child2 : Parent
{
    public override void AddRaw(object anything)
    {
        MyTable2 t = (MyTable2) anything;
        ...
    }
}

I've background from javascript and python. It's so common to do such things in a "weak type" languages, and within which you can pass anything anywhere.

I've used <T> and delegate in C# before. But I cannot think of a way using them here.

What's the C# way of doing this?

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
hbrls
  • 2,110
  • 5
  • 32
  • 53

4 Answers4

3

You can use the dynamic keyword, an interface implementation or abstract base class, but I would personally prefer using as much typed members as possible.

Use of dynamic:

public override void AddRaw(dynamic anything)
{
    // pseudo code
    DataTable dt = new DataTable();
    foreach(row r in anything)
    {
        dt.AddRow(r);
    }

    this.Add(dt);
}

You can also do something like this, if you want to match anything and act based on the type:

public override void AddRaw(object anything)
{
    if (o is MyTable)
    { ... }
    else if (o is string)
    { ... }
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Thanks! `dynamic` was exactly what I was hoping to have. But the other answers provided alternatives. I have to think about which is the best answer. – hbrls Mar 06 '14 at 10:00
  • @hbrlovehaku: If inheritance is an option, use that. (please... your life will not get better using `dynamic`) – Patrick Hofman Mar 06 '14 at 10:02
  • No, we're still discussing the requirements. – hbrls Mar 07 '14 at 03:57
  • This answered the original question best. However, I've not made up my mind to use this `dynamic`. – hbrls Mar 12 '14 at 07:16
0

How about overloading your method?

class Parent
{
    protected void Add(DataTable dt) { ... }
}

class Child1:Parent
{
    public void Add(MyTable1 anything)
    {
        // pseudo code
        DataTable dt = new DataTable();
        foreach(row r in anything)
        {
            dt.AddRow(r);
        }

        this.Add(dt);
    }
}

class Child2:Parent
{
    public void Add(MyTable2 anything)
    {
        ...
    }
}
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
  • I may want to use delegate in the future. I'm not sure if `overloading` is OK with that. – hbrls Mar 06 '14 at 09:57
  • @hbrlovehaku based on [this link](http://bytes.com/topic/c-sharp/answers/533114-delegates-overloaded-methods) it should be OK – WiiMaxx Mar 06 '14 at 10:28
  • @hbrlovehaku [here](http://stackoverflow.com/a/3747953/1993545) is also an example how you could use a delegate – WiiMaxx Mar 06 '14 at 10:31
0

You can make the parent class generic:

class Parent<T>
{
    protected void Add(DataTable dt) { ... }        // the real business logics
    public virtual void AddRaw(T anything) {}
}

class Child1 : Parent<MyTable1>
{
    public override void AddRaw(MyTable1 anything) { ... }
}

class Child2 : Parent<MyTable2>
{
    public override void AddRaw(MyTable2 anything) { ... }
}

In addition, I'd suggest to make Parent abstract, unless you really need to create Parent instances:

abstract class Parent<T>
{
    protected void Add(DataTable dt) { ... }        // the real business logics
    public abstract void AddRaw(T anything);
}

That way, the compiler ensures that every client must implement AddRaw.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • You suggestion seems the most elegant. But I still have a question. What if I want to `Child : Parent`, `GrandChild : Child `? – hbrls Mar 06 '14 at 10:26
  • @hbrlovehaku: You can't. And you don't want to. Please explain in plain English what this would mean. You can't... – Patrick Hofman Mar 06 '14 at 10:30
0

I think I'd use an adapter resolver class. Create each adapter in their own class and register them with a static class along with the type they adapter

Adapters.Register(typeof(MyTable), MyTableAdapter)

or // void Register(Adapter) and MyTableAdapter: Adapter Adapters.Register(MyTableAdapter)

then you'd request an adapter from the the Adapters list

Adapters.GetAdapter<MyTable>();

where you could return a sensible error if no adapters for that type had been registered

James
  • 9,774
  • 5
  • 34
  • 58