Inheritance and Property Indexes

ScaleOut Software NamedCache API

Properties annotated with the SossIndexAttribute may be virtual. In this section, we review how overridden properties, explicit interface properties, and property hiding is implemented within the StateServer property index.

Virtual Properties and the Property Index

For example, consider:

[Serializable]
abstract class Shape
{
    [SossIndex]
    public abstract double Area { get; }
}

[Serializable]
class Circle : Shape
{
    // assume this get set somehow ...
    double radius = 0;
    public override double Area
    {
        get { return Math.PI * radius * radius; }
    }
}

[Serializable]
class Rectangle : Shape
{
    // assume these get set somehow ...
    double width = 0, height = 0;
    public override double Area
    {
        get { return width * height; }
    }
}
Note that the Area property is abstract in the base class. Consequently, the Area property must always be overridden by any subclass. However, you can still query against the base class for (overridden) Area values as shown below:
NamedCache cache = CacheFactory.GetCache("Shapes");
var smallShapes = from s in cache.QueryObjects<Shape>()
                  where s.Area < .1
                  select new { s.Area, s.GetType().Name };

double average = smallShapes.Select(s => s.Area).Average();
int countWhenRectangle = smallShapes.Where(s => s.Name == "Rectangle").Count();
int countWhenCircle = smallShapes.Where(s => s.Name == "Circle").Count();

When a subclass overrides a property defined in a base class, it doesn't matter if the subclass annotates the overridden property with SossIndexAttribute. When the overridden property's value is copied to StateServer's property index the overridden value is written to the property index.

Hidden Properties and the Property Index

.Net also supports the notion of subclasses hiding properties in their base classes. In this case, even though the properties have the same name, they are treated as distinct properties.

Consider the following example:

[Serializable]
class Base
{
    [SossIndex]
    public double Prop
    {
        get { return 1; }
    }
}

[Serializable]
class SubClass : Base
{
    public new double Prop
    {
        get { return -1; }
    }
}
When you query objects while filtering against Base class as shown below
var queryBase = from b in cache.QueryObjects<Base>()
                where b.Prop > 0
                select b;

Console.WriteLine("Found {0} objects", queryBase.Count());
the query succeeds and returns the count of all objects of type Base as well as any SubClass objects.

However, when you query objects while filtering against SubClass as shown here

var querySub = from s in cache.QueryObjects<SubClass>()
               where s.Prop < 0
               select s;

Console.WriteLine("Found {0} objects", querySub.Count());
the query provider throws an exception at runtime when the query is evaluated because Prop hides the base class's Prop property and is therefore considered an independent property. However, the SubClass's Prop implementation is not annotated with SossIndexAttribute. Consequently, the Prop property from SubClass is not in StateServer's property index and the query cannot be evaluated on the server.

If SubClass is modified by annotating Prop with SossIndexAttribute as shown here

[Serializable]
class Base
{
    [SossIndex]
    public double Prop
    {
        get { return 1; }
    }
}

[Serializable]
class SubClass : Base
{
    [SossIndex]
    public new double Prop
    {
        get { return -1; }
    }
}
then this query
var querySub = from s in cache.QueryObjects<SubClass>()
               where s.Prop < 0
               select s;

Console.WriteLine("Found {0} objects", querySub.Count());
will succeed and return the count of SubClass instances.

Interfaces and the Property Index

The SossIndexAttribute may be used with properties defined on interfaces. In that case, any type that implements the interface implicitly annotates its implementation of properties annotated on the interface. Essentially, the SossIndexAttribute annotation becomes part of the interface contract.

On the other hand, because interfaces have no implementation, the NamedCache never writes type signature information to the StateServer property index for interfaces. As a result, you cannot filter objects from a NamedCache by interface.

See Also

Other Resources