views:

50

answers:

1

Now, I am working on ASP.NET MVC 2. I just found some serious problem about View Model class that derives from base class in Model project. Every time when I fetch data from database, I have to cast it to View Model instance that is not possible in most OOP language.

Base class

public class MyBaseClass
{
    public string ID { get;set; }
    public string Value { get;set; }
}

Derived class

public class MyDerivedClass : MyBaseClass, ISomeInterface
{
    // logic for My Derived Class
}

However, I try to create some method that copy all readable property from instance of base class to instance of derived class like the following code.

public static TDerived CastObject<TBase, TDerived>(TBase baseObj)
{
    Type baseType = typeof(TBase);
    Type derivedType = typeof(TDerived);

    if (!baseType.IsAssignableFrom(derivedType))
    {
        throw new Exception("TBase must be a parent of TDerived.");
    }

    TDerived derivedObj = Activator.CreateInstance<TDerived>();

    foreach (PropertyInfo pi in baseType.GetProperties())
    {
        if (pi.CanRead)
        {
            PropertyInfo derivedProperty = derivedType.GetProperty(pi.Name);

            if (derivedProperty.CanWrite)
            {
                derivedProperty.SetValue(derivedObj, pi.GetValue(baseObj, null), null);
            }
        }
    }

    return derivedObj;
}

But I do not sure about the above code that will work great on large-scale website and there are a lot of feature in DLR of C# 4.0 that I do not know.

Do you have any idea for converting item by using C# 4.0?

Thanks,

+1  A: 

Is there any reason why the base type couldn't have a constructor which took an instance to copy data from?

public class MyBaseClass
{
    public string ID { get;set; }
    public string Value { get;set; }

    public MyBaseClass() {}

    public MyBaseClass(MyBaseClass other)
    {
        ID = other.ID;
        Value = other.Value;
    }
}


public class MyDerivedClass : MyBaseClass, ISomeInterface
{
    public MyDerivedClass(MyBaseClass other) : base(other)
    {           
    }
}

Alternatively, could you do this with composition instead of inheritance? Could your derived class keep a reference to the instance of MyBaseClass to get its value and ID from?

Finally, could you change the data access layer so that it could create an instance of the right class to start with?

Jon Skeet
It is very easy as you answer. But it does not work because base class is generated by POCO template of EF 4.0 on VS 2010 B2.
Soul_Master
@Soul_Master: Is it generated as a partial class? If so, you can add your own constructor in another file.
Jon Skeet
It should be very bad idea. Because when property in generated class is changed, you must change your constructor in partial class too. It does not make sense for me. I think my current solution should work well on large scale project more than your solution.
Soul_Master
The requirement sounds like a bad idea to start with, IMO. Yes, you need to be careful with the "copy constructor" idea - but I think I'd prefer that to reflection. Heck, you could easily autogenerate the file containing the constructor - that way it would be robust in the face of changes, but without the downsides of reflection.
Jon Skeet