views:

67

answers:

2

First thing to note - I KNOW DELEGATION AND DECORATOR PATTERNS!

Second - I am using C# .NET 4.0, so if you come up with a solution that is specific for it, that's fine. But if solution will work for any OOP language and platform, that would be great.

And here the question goes...

I have a partial class (lets name it Class1), which I cannot modify. Thus, I can just extend it or/and inherit from it. This class provides a perfect data model for me, the only thing I need is to add some attributes to its properties (for validation, defining label text value in MVC etc - for now, I do not need answers like 'you can do what you need without attributes', that's not the matter of my question).

It is not a problem to use another class as a data model, so I can, say, create Class2 : Class1 and use Class2 as a model. Properties that need attributes would be defined as public new <type> <propertyname>. This will limit me to rewriting only the properties that need attributes, leaving all other untouched.

The smaller problem is that I do not what to redefine getters and setters for the properties, as all they gonna contain is return base.<propertyname> and base.<propertyname> = value, and if there are lots of such properties, this means lots of "stupid" coding. Is there a way to avoid this?

The bigger problem is that I have to parametrize my Class2 with Class1 instance and make something like class2.<propertyname> = class1.<propertyname> for each single property I have - too much of "stupid" coding. I can avoid it using reflection - find all properties with public getters and setters in Class1 and call prop.SetValue(child, prop.GetValue(parent, null), null); in the loop. This provides a generic function for simple cases, which is quite fine, as I mostly have simple models - lots of properties with public getters and setters without body and another logic. But I want more generic solution, and I do not like reflection. Any ideas?

Here goes the full code of the extension method that creates Class2 basing on Class1

    public static Child ToExtendedChild<Parent, Child>(this Parent parent)
        where Child : Parent, new()
    {
        Child child = new Child();

        var props = typeof(Parent).GetProperties().Where(p => p.GetAccessors().Count() >= 2);

        foreach (var prop in props)
        {
            prop.SetValue(child, prop.GetValue(parent, null), null);
        }

        return child;
    }

(by the way, this method may not ideally implement my solution, so any corrections would also be appreciated)

Thanks in advance!

+1  A: 

I assume the partial class is generated code, it makes the most sense given your scenario.

I know of one way to do this, but depending on how the attribute gets crawled, it may not work.

// Generated Code
public partial Class1
{
  public string Foo { get { ... } }
}

// Your Code
public interface IClass1
{
  [MyAttribute]
  public string Foo { get; }
}

public partial Class1 : IClass1
{
}

If someone were to look at attributes by using GetCustomAttributes with inheritance, then I think they would get this attribute.

As an aside, whenever I see generated code that doesn't have virtual properties it makes me cry a little bit inside.

To address your bigger question, why don't you just make Class2 a wrapper for Class1. Instead of copying all of the properties you can just give Class2 an instance of Class1 in the constructor, store it locally and make all of your properties pass-throughs. It means some hand coding, but if you're building a Class2 by hand anyway and want to decorate it with a bunch of attributes, well, you're hand coding Class2 anyway.

Hounshell
I will definitely try your interface approach, it looks great if attributes are indeed get crawled with inheritance.
Michael Sagalovich
And making Class2 a wrapper is not what I am searching for, as in every property's body I will have to write `return class1.<propertyname>`, `class1.<propertyname> = value`, I want to avoid this - this means too much useless coding. My approach looks similar, but I define the bodies for only those properties that need attributes - this can make difference in some situations. Anyway, me bigger question may become just a theoretical one if interface approach works. Thank you!
Michael Sagalovich
A: 

The smaller problem doesn't seem to be much of a problem. Maybe I'm misunderstanding the question, but assuming you're simply deriving a subclass, there should be no reason to redefine either the properties or their associated getters/setters.

The bigger problem might be resolved using something a little simpler. Using reflection for a lot of your object initialization seems a little expensive. If you're dealing with a class that is primarily a big bag or properties, maybe you should as if you need access to all of those properties in any given situation. You mention MVC and validation, is the entire model being used in the controller method you're validation is taking place in? If not, why not look at using a viewmodel that only exposes those pieces you need in that method?

Your reflection initializer is interesting, but if you're going to be doing a lot of this then you might consider investing a little time with Automapper. Otherwise maybe consider moving away from a generic solution to something that just tackles the problem at hand, i.e. mapping properties from an instance of an object to another instance of a derived object. Maybe you can create a copy constructor in the parent class and use that in your derived class?

public class Foo {
    public string PropOne { get; set; }
    public string PropTwo { get; set; }

    public Foo(string propOne, string propTwo) {
        PropOne = propOne;
        PropTwo = propTwo;
    }

    public Foo(Foo foo) {
        PropOne = foo.PropOne;
        PropTwo = foo.PropTwo;
    }
}

public class Pho : Foo {
    // if you have additional properties then handle them here
    // and let the base class take care of the rest.
    public string PropThree { get; set; }
    public Pho(string propOne, string propTwo, string propThree) 
        : base(propOne, propTwo) {
        PropThree = propThree; 
    }
    public Pho(Pho pho) : base(pho) {
        PropThree = pho.PropThree;
    }
    // otherwise you can just rely on a copy constructor
    // to handle the initialization.
    public Pho(Foo foo) : base(foo) {}
}
RG
I have to redefine getters and setters as I am making properties `new`, and copy constructor is just one more variant of writing lots of lines like `property = property`
Michael Sagalovich
And thanks for AutoMapper - it's interesting, though I am not sure I want to import third-party solutions to tackle this minor problem.
Michael Sagalovich