Reputation: 129
The following codes works as is, but I would like to use a reference to the MyProperty class to be passed in the constructor instead of the strongly typed references in the inline code.
How do I do this, I expected to pass a ref to MyProperty but everything I have tried fails
I would like PropertyClass to be able to handle any MyProperty classes i.e. no references to MyProperty in PropertyClass
Still learning so sorry if I have missed the obvious !
Many Thanks for any help
Sarah
PropertyClass pc = new PropertyClass(!here!); // Would like to pass MyProperty class here
pc.Settings.Add(new MyProperty("Fred", "Monday"));
pc.SaveXml("MyTest.xml");
public class MyProperty
{
[XmlAttribute]
public string MyPropName { get; set; }
[XmlElement]
public string MyPropData { get; set; }
// default constructor needs to be parameterless for serialisation.
public MyProperty()
{
}
public MyProperty(string Name, string Data)
{
MyPropName = Name;
MyPropData = Data;
}
}
public class PropertyClass
{
public List<MyProperty> Settings { get; set; }
public PropertyClass() // How to pass the required class here ?
{ // public PropertyClass( ref MyProperty myprop)
Settings = new List<MyProperty>();
}
public void SaveXml(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
XmlSerializer XML = new XmlSerializer(typeof(List<MyProperty>), new XmlRootAttribute("Settings"));
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
XML.Serialize(stream, Settings, namespaces);
}
}
}
Upvotes: 0
Views: 2867
Reputation: 1646
I would change the definition of PropertyClass
to
public class PropertyClass<T>
{
public List<T> Settings { get; set; }
public PropertyClass()
{
Settings = new List<T>();
}
public void SaveXml(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
XmlSerializer XML = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("Settings"));
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
XML.Serialize(stream, Settings, namespaces);
}
}
}
The type parameter T
specifies the type of the items in the List<T>
, so that you can instantiate PropertyClass
as follows
var pc = new PropertyClass<MyProperty>();
Or when you get tired of MyProperty
you can change it to new PropertyClass<foo>()
without changing it elsewhere.
Another nice feature that I like about generics is that you can actually place constraints on the type parameter in the line where you declare it like:
public class PropertyClass<T> where T : MyClass, IMyInterface, new()
This means that T
has to be derived from MyClass
, it has to implement IMyInterface
and has to have a parameterless constructor. (Obviously you do not need to add all such constraints, but they can all be useful in certain cases).
I want to rant a little more, but I am sure you can play with it and find some uses for it.
Upvotes: 3
Reputation: 45096
this is how you call the constructor
PropertyClass pc = new PropertyClass(new MyProperty("Fred", "Monday"));
this is the constructor
Public MyProperty MyProperty { get; set; }
public PropertyClass(MyProperty _myProperty)
{
MyProperty = _myProperty
}
Upvotes: 0
Reputation: 81
Work on your naming, it wasn't immediately obvious that PropertyClass was actually a collection of properties; perhaps MyPropertyCollection would be better?
What you're looking for is called constructor overloading. Basically you specify the constructor again, but this time with parameters:
public MyPropertyCollection()
{
Settings = new List<MyProperty>();
}
public MyPropertyCollection(IEnumerable<MyProperty> collection)
{
Settings = new List<MyProperty>(collection);
}
Or to allow var col = new MyPropertyCollection(new MyProperty(), new MyProperty(), new MyProperty())
you can do:
public MyPropertyCollection(params MyProperty[] collection)
{
Settings = new List<MyProperty>(collection);
}
Though you should be careful with that, it doesn't feel right and should you later want to introduce additional parameters, well it could end bad.
Also, as you're basically wrapping a list, what you could also consider is the System.Collection.ObjectModel.Collection<T>
class as a base:
// The Collection<MyProperty> base class is responsible for maintaining the list
public class MyPropertyCollection : Collection<MyProperty>
{
public MyPropertyCollection()
{
// Default base() constructor is called automatically
}
public MyPropertyCollection(IList<MyProperty> properties)
: base(properties)
{
// Overloaded constructor calls base constructor with collection of properties
}
public void SaveXml(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Create))
{
// Serializer should now target this very class
var xml = new XmlSerializer(typeof (this), new XmlRootAttribute("Settings"));
var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
xml.Serialize(stream, this, namespaces);
}
}
}
Upvotes: 1
Reputation: 100527
Possibly you are looking for generics:
public class PropertyClass<TMyProperty>
{
public List<TMyProperty> Settings { get; set; }
public PropertyClass()
{
Settings = new List<TMyProperty>();
}
..
}
Upvotes: 1
Reputation: 4410
I think you need a generic class.
public class PropertyClass<T>
{
public List<T> Settings { get; set; }
public PropertyClass()
{
Settings = new List<T>();
}
...
}
PropertyClass<MyProperty> pc = new PropertyClass<MyProperty>();
I must add that your naming is very unclear. PropertyClass
should be called something like XmlableList
. And MyProperty
already exists and is called NameValuePair<string,string>
Upvotes: 1
Reputation: 152556
You need to add a constructor that takes a MyProperty
as an argument:
public PropertyClass(MyProperty myprop)
{
Settings = new List<MyProperty> {myprop};
}
Note that MyProperty
is a reference type so ref
is unnecessary here (it already is a reference).
Upvotes: 0