Sarah T
Sarah T

Reputation: 129

c# passing class argument to constructor

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

Answers (6)

Nameless One
Nameless One

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

paparazzo
paparazzo

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

diepvriezer
diepvriezer

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

Alexei Levenkov
Alexei Levenkov

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

yu_sha
yu_sha

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

D Stanley
D Stanley

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

Related Questions