views:

91

answers:

4
public class DTOa
{
    public int Id { get; set;}
    public string FirstName { get; set;}
}

public class DTOb: DTOa
{
    public string Email { get; set;}
    public string Password { get; set; }
}

public class a
{
    protected DTOa _DTO = new DTOa();
    public int Id
    {
        get
        {
            return _DTO.Id;
        }
        set
        {
            _DTO.Id = value;
        }
    }

    public string FirstName
    {
        get
        {
            return _DTO.FirstName;
        }
        set
        {
            _DTO.FirstName = value;
        }
    }

    public DTOa ToValueObject()
    {
        return _DTO;
    }
}

public class b: a
{
    protected DTOb _DTO = new DTOb();

    public string Email
    {
        get
        {
            return _DTO.Email;
        }

        set
        {
            _DTO.Email = value;
        }
    }

     public string Password
    {
        get
        {
            return _DTO.Password;
        }

        set
        {
            _DTO.Password  = value;
        }
    }

    public DTOb ToValueObject()
    {
        return _DTO;
    }
}

now let's execute the following code

public function test() 
{       
   var a = new a();
   var b = new b();
   b.Id = 100;
   b.FirstName = "Jim";
   b.Email = "[email protected]";
   b.Password = "test";
   Console.WriteLine(b.ToValueObject().Dump());
}

the problem is that

  1. I expect b.ToValueObject have all properties set, but in reality only get properties from DTOb class (so I FirstName and Id properties are NULL, however I set the explicitly)

    dump:

    { Email: [email protected], Password: test, Id: 0 }

Any ideas why ID is not set and FirstName is not set? DTOb is inherited from DTOa and thus "Should" include all the properties from DTOa. It's working on the code level, so if I write console.WriteLine(b.Firstname) - I'll get the value correct, but when I call ToValueObject() method - it got deleted.


OKay here is working example:

public class DTOa : IDTO
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

public class DTOb : DTOa, IDTO
{

    public string Email { get; set; }
    public string Password { get; set; }
}

public class a
{
    protected IDTO _DTO;

    public a()
    {
        _DTO = new DTOa();
    }

    public int Id
    {
        get
        {
            return (_DTO as DTOa).Id;
        }
        set
        {
            (_DTO as DTOa).Id = value;
        }
    }

    public string FirstName
    {
        get
        {
            return (_DTO as DTOa).FirstName;
        }
        set
        {
            (_DTO as DTOa).FirstName = value;
        }
    }

    public DTOa ToValueObject()
    {
        return (_DTO as DTOa);
    }

}

public class b : a
{
    public b()
    {
        _DTO = new DTOb();
    }

    public string Email
    {
        get
        {
            return (_DTO as DTOb).Email;
        }

        set
        {
            (_DTO as DTOb).Email = value;
        }
    }

    public string Password
    {
        get
        {
            return (_DTO as DTOb).Password;
        }

        set
        {
            (_DTO as DTOb).Password = value;
        }
    }

    public DTOb ToValueObject()
    {
        return _DTO as DTOb;
    }
}
+6  A: 

DTOb is inherited from DTOa and thus "Should" include all the properties from DTOa

This is true, but you also have this:

public class a
{
    protected DTOa _DTO = new DTOa();
    ...
}

public class b
{
    protected DTOb _DTO = new DTOb();
    ...
}

That is, class a and b are both working with different instances of the "DTO" class. In fact, your compiler should be giving you a warning about the _DTO in b "hiding" the _DTO field in a.

What you want to do is make sure that both classes are accessing the same instance. You can't override fields, but you can override methods so something like this might be suitable:

class A
{
    private DTOa _dto = new DTOa();
    protected virtual DTOa GetDTO()
    {
        return _dto;
    }

    public string FirstName
    {
        get { return GetDTO().FirstName; }
        set { GetDTO().FirstName = value; }
    }

    ...
}

class B : A
{
    private DTOb _dto = new DTOb();
    protected virtual DTOa GetDTO()
    {
        return _dto;
    }

    public string Email
    {
        get { return GetDTO().Email; }
        set { GetDTO().Email = value; }
    }

    ...
}

To be honest, I'm not quite sure what the benefit of this "DTO" object is, but the above should give you the behaviour you're after.

Dean Harding
Beat me to it, though I was going to point out you can override properties.
NickLarsen
the problem is B will contain both a DTOa and a DTOb, so the Id and FirstName fields will be duplicated.
Mark H
@Mark H: yes, but in B, the DTOa instance will basically be unused. You can do a lazy construction of the backing field if you don't want that extra instance hanging around.
Dean Harding
@NickLarsen: That's a good point, a property would probably be a more "natural" choice...
Dean Harding
that method doesn't work, because in class B, when you typeGetDTO().Email = valuethe Email property is not a part of DTOa class, but DTOb instead.
Dmitry
+1 for catching the confusing of instances and class defs - common problem starting making objects.
FastAl
@Dmitry: that's exactly the point, though. When you call `B`'s `ToValueObject` method, you get the DTOb instance back, and so you *want* all the properties from `A` to be in there.
Dean Harding
@Dean 'codeka' Harding: I understand that totally, but it still doesn't work. I'm trying to return DTOb in b.toValueObject() call which will have all properties set, since it's inherited from DTOa. So far no luck, but I'm trying .... trying )
Dmitry
Okay pls see my refactoring above
Dmitry
A: 

This is because your b class makes its own DTO object (protected DTOb _DTO = new DTOb()) and modifies this and your a class makes its own DTO object (protected DTOa _DTO = new DTOa()) and modifies this.

At no stage does your b class pass its object up to a to be modified.

Furthermore, your GetValueObject is only going to return the instance within that class.

To get what you want you need a property like:

public DTOa DTO { get; }

Which is overridden in your b class, and make sure all your set methods set through this call. You'll have to do some casting with your b one though when you use it.

Graphain
A: 

You should be getting warnings about your _DTO field and ToValueObject method hiding the corresponding field/method from class a. What is happening is that the class b object has both a DTOa and a DTOb object both known as _DTO and the methods in a refer to the DTOa object and the methods in b refer to the DTOb object.

Personally I think you're going at this the wrong way. It looks like you're trying to model a user and a user with contact information. I'd suggest that there isn't really an inheritance relationship ("is a") here, but rather a "has a" relationship -- a user has contact information. If you modeled it this way you'd have UserDTO and a ContactDTO and your user object would contain both a UserDTO and a ContactDTO (or a reference to a Contact which has a ContactDTO object).

tvanfosson
A: 

I see little point in duplicating the functionality of DTOa and DTOb with your a and b classes. It's generally an anti-pattern, unless you have a specific reason to intercept the values before they reach DTOa.

Anyway, you can fix your code using some generics.

public class a<T> where T : DTOa {
    private readonly T _DTO = Activator.CreateInstance<T>();

    protected T DTO { get { return this._DTO; } }

    //properties
}

public class b<T> : a<T> where T : DTOb {
    //NB: Don't override or hide DTO.
    //properties
}


var a = new a<DTOa>();
var b = new b<DTOb>();
b.Id = 100;
b.FirstName = "Jim";
b.Email = "[email protected]";
b.Password = "test";
Mark H
Interesting- thank you!
Dmitry