Creating objects polymorphically

  • Thread starter Thread starter Peter Morris
  • Start date Start date
P

Peter Morris

Hi all

Let's say I am creating a model to represent classes and properties. In
addition to this I need instances of classes and values for those
properties.

KEY:
[ClassName]
(AssociationEndName)


A classifier has many properties
[Classifier] (Classifier) 1-----* (Properties) [Property]

A classifier has many instances
[Classifier] (Classifier) 1-----* (Instances) [Instance]

An instance has many property values
[Instance] (Instance) 1----* (PropertyValues) [PropertyValue]

A Property has many PropertyValues
[Property] (Property) 1----* (PropertyValues) [PropertyValue]


I hope that's clear :-)

var personClassifier = new Classifier();
var firstNameProperty = new Property();
personClassifier.Properties.Add(firstNameProperty);

At this point I want to do something like this

var personInstance = Instance.FromClassifier(personClassifier);

the implementation would look something like this

public static Instance FromClassifier(Classifier classifier)
{
var result = new Instance();
result.Classifier = classifier;

foreach (var property in classifier.Properties)
{
var propertyValue = new PropertyValue();
result.PropertyValues.Add(propertyValue);
propertyValue.Property = property;
}
}

The above is a simple example. The fact is I have a pre-defined set of
property types. So descended from Property I might have

StringProperty, NumericProperty, BooleanProperty, etc

and a corresponding PropertyValue class for each

StringPropertyValue, NumericPropertyValue, BooleanPropertyValue, etc


To achieve the creation of the correct PropertyValue descendant I added an
abstract method to Property

public abstract PropertyValue CreatePropertyValue(Property property);

and implement in each descendant

public override PropertyValue CreatePropertyValue(Property property)
{
var result = new BooleanPropertyValue();
result.StronglyTypedReference = (BooleanProperty)property;
return result;
}


Now onto the question :-)

To me this seems logical, but a little messy. I don't like the fact that
the Property class creates the instance of the PropertyValue. What I would
expect to write in code is something like

var property = BooleanPropertyValue.FromProperty(booleanProperty);

but obviously in this case I can't hard-code the class type into my foreach
loop. So it seems I am stuck with the Property being responsible for
creating the correct PropertyValue instances. Or do I have another option?
 
Peter said:
Hi all

Let's say I am creating a model to represent classes and properties.
In addition to this I need instances of classes and values for those
properties.

Rebuilding the Delphi "class of class" metaclasses? AFAIK, Joanna
Carter once wrote a nice article on this, IOW, how to do this using C#.
--
Rudy Velthuis http://rvelthuis.de

"I'm not under the alkafluence of inkahol that some thinkle
peep I am. It's just the drunker I sit here the longer I get."
-- Unknown
 
I'm actually building messages from templates. For example

[MessageTemplate] (Template) 1-----* (Properties) [MessageTemplateProperty]

The MessageTemplate might be something like

Name : string;
=========
Message : string;
Discount : decimal;


So I would create 1 MessageTemplate, and
MessageTemplateStringProperty
MessageTemplateNumericalProperty

That's the template defined by some kind of admin, now the users will create
messages based on it...

Name = "10% off handbags"
Message = "This week only. 10% of all marked prices on handbags!!!"
Discount = 10m;

Name = "15% off squirrels"
Message = "This week only. 15% of all marked prices on squirrels!!!"
Discount = 15m;


This information gets packaged up as XML something like this

<messages>
<message id="1" templateID="{GuidOfTheTemplate}">
<values>
<value id="{GuidOfTheTemplateProperty}">
This week only. 10% of all marked prices on handbags!!!"
</value>
<value name="{GuidOfTheTemplateProperty}">
10
</value>
</values>
</message>
<message id="1" templateID="{GuidOfTheTemplate}">
<values>
<value id="{GuidOfTheTemplateProperty}">
This week only. 15% of all marked prices on squirrels!!!"
</value>
<value name="{GuidOfTheTemplateProperty}">
15
</value>
</values>
</message></messages>

It's concocted, but illustrates the point :-)

Having a virtual method on the abstract MessageTemplateProperty does the
trick, but there's just something about it that makes me feel dirty, and not
good dirty :-) I was hoping there was a pattern or something that might
make more sense, otherwise I will just leave it as it is :-)

Thinking about it, I use the service provider pattern throughout my system.
Maybe I should create something like this:

public interface IMessagePropertyFactory
{
MessageProperty CreateMessageProperty(MessageTemplateProperty
templateProperty);
}

I can then get this factory from my service provider, which would mean I can
mock it easily and check that it is being called from a unit test. Or maybe
that is overkill :-)
 
Back
Top