RegisterProperty for derived classes in 4.0

RegisterProperty for derived classes in 4.0

Old forum URL: forums.lhotka.net/forums/t/9191.aspx


nelis posted on Friday, July 09, 2010

RegisterProperty registers all properties with the type specified by the generic argument T.

Given this example:

 public abstract class SomeBase : BusinessBase<SomeBase>
{
    public static PropertyInfo<int> BaseIntProperty = RegisterProperty(new PropertyInfo<int>("BaseInt"));
}

public class SomeDerived1 : SomeBase
{
    public static PropertyInfo<int> Int1Property = RegisterProperty(new PropertyInfo<int>("Int1"));
}

public class SomeDerived2 : SomeBase
{
    public static PropertyInfo<int> Int2Property = RegisterProperty(new PropertyInfo<int>("Int2"));
}

Int1 and Int2 are registered with SomeBase not with SomeDerived1 and SomeDerived2. I didn't really expect that. Is this as it is supposed to?

Furthermore once you create an instance of SomeDerived1 the property list for SomeBase gets locked. Then instantiating SomeDerived2 will result in the InvalidOperationException:

Can not register property Int2 after containing type (SomeBase) has been instantiated

 

Some thoughts:

- Shouldn't properties be registered with their DeclaringType. For the overloads using the lambda expression that value is available from reflectedPropertyInfo. For the other overloads you could use StackTrace to find out the calling (decalring) type but that might be expensive. An alternative is specifying it as an extra argument to RegisterProperty but that won't guarantee that the specified type equals the declaring type. That however can be checked from the System.Reflection.PropertyInfo.

- The overloads using lambda expressions can not be used from derived classes. You could however specify an overload like:

protected static TjipPropertyInfo<P> RegisterProperty<C, P>(Expression<Func<C, object>>...
    where C : T

Not ideal but it provides intellisense assistance

RockfordLhotka replied on Friday, July 09, 2010

When creating an abstract base type, that type must be generic. Or you can't use the generic overloads of RegisterProperty() - the choice is yours.

Obviously the type T is frozen at the point where your types become non-generic - that's the way generics work.

Using things like stack traces and whatnot is not only slow, but unreliable. Look at CSLA 2 and some of the ways it used that technique - then see how those techniques are gone now? That's because the .NET JIT compilers added optimizations that entirely break that technique. Things that work in debug mode may or may not work in 32 or 64 bit JIT release mode.

In short: your base types must be generic, or you must avoid the generic overloads of RegisterProperty().

nelis replied on Monday, July 12, 2010

I understand, but what I am saying is that you can't even use the non-generic overloads of RegisterProperty if you have multiple derived classes

RockfordLhotka replied on Monday, July 12, 2010

Let me try to be more clear then.

Multiple derived non-generic classes are not supported by BusinessBase<T> or the other generic base classes. You can have multiple derived classes, but they must be generic.

If you want multiple non-generic classes, then you must derive from Csla.Core.BusinessBase. You'll give up some functionality, but you also avoid the limitations imposed by generics.

Copyright (c) Marimer LLC