How can you apply the Adapter Pattern to a Collection? - c#

Given the two classes below, how can I
convert List<Person> to
List<Person2>?
EDIT: This is a fabricated example. The point I'm trying to make is that I can't modify the Person class, and we'll know arbitraryNumber when we instantiate List<Person2>.
EDIT2: I know that many of you will find this unbelievable, but this code will be deployed to a Windows-Server-2000 machine, which means that it must work with .NET 2.0. [Yes - I find this to be unbelievable as well.]
public class Person
{
private string _lastName;
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
}
public class Person2 : Person
{
private readonly int _arbitraryNumber;
public Person2(int arbitraryNumber)
{
_arbitraryNumber = arbitraryNumber;
}
public string FullName
{
get
{
return String.Format("{0}, {1} - {2}", LastName, FirstName, _arbitraryNumber);
}
}
}

I think Person2 needs to change to be an adapter. Something like this
public class Person2
{
private readonly int _arbitraryNumber;
private readonly Person _person;
public Person2(Person person, int arbitraryNumber)
{
_arbitraryNumber = arbitraryNumber;
_person = person;
}
public string FullName
{
get
{
return String.Format("{0}, {1} - {2}", _person.LastName, _person.FirstName, _arbitraryNumber);
}
}
}
Then the adapter on the collection is easier.
List<Person> persons = new List<Person>();
// put some people in it.
var person2s = persons.Select(p => new Person2(4, p)); // 4 chosen arbitrarily
Or for .NET 2
List<Person2> person2s = new List<Person2>();
foreach (Person p in persons)
{
Person2 person2 = new Person2(p, 11); // 11 arbitrarily chosen by asking a kid for a number
person2s.Add(person2);
}

Related

Printing out list to console

I am trying to output the whole list to console, but all I end up getting is the message "Stack overflow 19277 times". Can someone please help me out? I have now added the rest of the code. As you can see, the list wont print to console. I have tried many ways. The ideal solution would be a PrintAllEmployees-method to console under the company class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Entities
{
public class Person
{
private string name;
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public Person(string name, int age)
{
name = Name;
age = Age;
}
}
public class Employee : Person
{
public string hireDate;
public Employee(string name, int age, string hireDate) : base(name, age)
{
hireDate = HireDate;
}
public string HireDate
{
get { return hireDate; }
set { hireDate = value; }
}
}
public class Company
{
public List<Person> employeesList = new List<Person>();
public string companyName
{
get { return companyName; }
set { companyName = value; }
}
public int employeeCount
{
get { return employeeCount; }
set { employeeCount = value; }
}
public Company(string CompanyName, int EmployeeCount)
{
EmployeeCount = employeeCount;
CompanyName = companyName;
}
}
}
using Entities;
namespace Checkpoint_2___Console_App
{
public class Program
{
static void Main(string[] args)
{
List<Person> employeesList = new List<Person>();
Person myPerson = new("Kari", 35);
Employee myEmployee = new("Ole", 35, "10.10.2000");
Company myCompany = new("Baker Hansen", 15);
employeesList.Add(myPerson);
employeesList.Add(myEmployee);
}
}
}
Look at this code:
public string companyName
{
get { return companyName; }
...
It says, "If you want to know the company name, you need to know the company name". That leads to stack overflow, because it keeps looping.
I guess what you meant was:
public string CompanyName
{
get { return companyName; }
...
Convention is that property names start with uppercase, private members with lower case.
The same goes for employeeCount.

How to implement the client using this example

I am using this Return list in WCF example but I cannot implemment the client code correctly. The example works. I want the list transfered on the client side.
My code so far:
List<Person> aPerson = new List<Person>()
Person y = new Person()'
aPerson.Add(y.id, y.name, y.adress, y.salary, y.country)
This is the server:
[DataContract]
public class Person
{
public string Id;
public string name;
public string address;
public string salary;
public string country;
public Person()
{ }
public Person(string _id, string _name, string _address, string _salary, string _country)
{
Id = _id;
name = _name;
address = _address;
salary = _salary;
country = _country;
}
[DataMember]
public string Idps
{
get { return Id; }
set { Id = value; }
}
[DataMember]
public string nameps
{
get { return name; }
set { name = value; }
}
[DataMember]
public string addressps
{
get { return address; }
set { address = value; }
}
[DataMember]
public string salaryps
{
get { return salary; }
set { salary = value; }
}
[DataMember]
public string countryps
{
get { return country; }
set { country = value; }
}
}
public List <Person> GetData(string Id)
{
//Create a List of Person objects
List<Person>employeelist =new List<Person>();
employeelist.Add(new Person("10", "name", "myAdress", "1000", "myCountry");
}
//Return the list that contains Person objects
return employeelist;
}
I don't know how to implement the client side using the code above. The server returns the list and I want to store the list local at the client.
I think you are best off walking through a full end-to-end example as found here: http://msdn.microsoft.com/en-us/library/bb386386.aspx which should help you get up to speed with WCF.
However, as a jump start... I assume that in your interface you have decorated your method GetData with the [OperationContract] attribute?
Then on the client you need to reference the WCF Service. When adding the service you should click on the Advanced button in the lower-left corner of the dialog. Change the Collection type drop-down from System.Array to
System.Collections.Generic.List.
Finally, your client should be able to call the service with some code like this:
public void SampleClientCode()
{
using (var client = new ServiceReference1.Service1Client())
{
List<Person> results = client.GetData("12345");
// Now do something with the data... Example
string firstPersonsName = results.First().nameps;
}
}
NOTE: Your property naming convention in your Person class is not very good and should be revised.

How do i use this class in the main function? Dictionaries and indexers (Collections)

I am trying to add entries in dictionary array list but i don't know which arguments to set in the People Class in the main function.
public class People : DictionaryBase
{
public void Add(Person newPerson)
{
Dictionary.Add(newPerson.Name, newPerson);
}
public void Remove(string name)
{
Dictionary.Remove(name);
}
public Person this[string name]
{
get
{
return (Person)Dictionary[name];
}
set
{
Dictionary[name] = value;
}
}
}
public class Person
{
private string name;
private int age;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
using this seem to give me error
static void Main(string[] args)
{
People peop = new People();
peop.Add("Josh", new Person("Josh"));
}
Error 2 No overload for method 'Add' takes 2 arguments
This peop.Add("Josh", new Person("Josh"));
should be this
var josh = new Person() // parameterless constructor.
{
Name = "Josh" //Setter for name.
};
peop.Add(josh);//adds person to dictionary.
The class People has the method Add which only takes one argument: a Person object. The Add on the people class method will take care of adding the it to the dictionary for you and supplying both the name (string) argument and the Person argument.
Your Person class only has a parameterless constructor, which means that you need to set your Name in the setter. You can do this when you instantiate the object like above.
For your design this would solve the problem:
public class People : DictionaryBase
{
public void Add(string key, Person newPerson)
{
Dictionary.Add(key , newPerson);
}
public void Remove(string name)
{
Dictionary.Remove(name);
}
public Person this[string name]
{
get
{
return (Person)Dictionary[name];
}
set
{
Dictionary[name] = value;
}
}
}
public class Person
{
private string name;
private int age;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
And in Main:
People peop = new People();
peop.Add("Josh", new Person() { Name = "Josh" });

can't call methods from my class.cs

i was need to write 2 methods in my student class which do the following
hasPassed() Should return True if the student has a year mark >= 40 or
false if the marks is <40
toString() Should return a single string containing a summary of the
student details held within the class
e.g.
“12345 Basil Fawlty, 23/08/1946”
here's the code i have for the above to methods, is what i have correct for what its asking for the above?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CourseWork
{
public class Student
{
private static string firstname;
private string secondname;
private string dateofbirth;
private string course;
private int matricnumber;
private double yearmark;
public bool hasPassed()
{
if (yearmark >= 40)
return true;
else
return false;
}
public void toString()
{
firstname = "Basil";
secondname = "Fawlty";
dateofbirth = "23/08/1946";
course = "MA Hotel Management";
matricnumber = 12345;
yearmark = 55;
}
public Student()
{
}
public string FirstName
{
get { return firstname; }
set { firstname = value; }
}
public string SecondName
{
get { return secondname; }
set { secondname = value; }
}
public string DateOfBirth
{
get { return dateofbirth; }
set { dateofbirth = value; }
}
public string Course
{
get { return course; }
set { course = value; }
}
public int MatricNumber
{
get { return matricnumber; }
set
{
if (value <= 99999 && value >= 10000)
{
matricnumber = value;
}
else
{
Console.WriteLine("Invalid Matric Number: {0}", value);
}
matricnumber = value;
}
}
public double YearMark
{
set
{
if (value <= 100 && value >= 0)
{
yearmark = value;
}
else
{
Console.WriteLine("Invalid Year Mark: {0}", value);
}
yearmark = value;
}
}
}
i then need the above methods to be used in a get button that does the following
Get: Uses the values of the Student class methods to update the text boxes. The
Student.hasPassed() method should be used to update the pass/fail label. The
Student details summary should be updated by using Student.toString ().
but I'm having trouble coding it and i cant seam to call hasPassed() method or toString() method from my student class
so I've doing something wrong but cant see what it is
any ideas how to go about fixing this?
In order the methods to be visible, you need to create an instance of the class Student. ex,
Student _student = new Student();
bool _x = _student.hasPassed();
if you want the members to be access without instantiating, make the member static,
public static bool hasPassed()
{
if (yearmark >= 40)
return true;
else
return false;
}
but bear in mind that static members cannot see non-static members. In that case, it won;t compile because yearmark cannot be found.

LinFu - can't quite see how to do what I want

Just found LinFu - looks very impressive, but I can't quite see how to do what I want to do - which is multiple inheritance by mixin (composition/delegation as I'd say in my VB5/6 days - when I had a tool to generate the tedious repetitive delegation code - it was whilst looking for a C# equivalent that I found LinFu).
FURTHER EDIT: TO clarify what I mean by composition/delegation and mixin.
public class Person : NEOtherBase, IName, IAge
{
public Person()
{
}
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Name "Mixin" - you'd need this code in any object that wanted to
//use the NameObject to implement IName
private NameObject _nameObj = new NameObject();
public string Name
{
get { return _nameObj.Name; }
set { _nameObj.Name = value; }
}
//--------------------
//Age "Mixin" you'd need this code in any object that wanted to
//use the AgeObject to implement IAge
private AgeObject _ageObj = new AgeObject();
public int Age
{
get { return _ageObj.Age; }
set { _ageObj.Age = value; }
}
//------------------
}
public interface IName
{
string Name { get; set; }
}
public class NameObject : IName
{
public NameObject()
{}
public NameObject(string name)
{
_name = name;
}
private string _name;
public string Name { get { return _name; } set { _name = value; } }
}
public interface IAge
{
int Age { get; set; }
}
public class AgeObject : IAge
{
public AgeObject()
{}
public AgeObject(int age)
{
_age = age;
}
private int _age;
public int Age { get { return _age; } set { _age = value; } }
}
Imagine objects with many more properties, used in many more "subclasses" and you start to see the tedium. A code-gernation tool would actually be just fine...
So, LinFu....
The mixin example below is fine but I'd want to have an actual Person class (as above) - what's the LinFu-esque way of doing that? Or have I missed the whole point?
EDIT: I need to be able to do this with classes that are already subclassed.
DynamicObject dynamic = new DynamicObject();
IPerson person = null;
// This will return false
bool isPerson = dynamic.LooksLike<IPerson>();
// Implement IPerson
dynamic.MixWith(new HasAge(18));
dynamic.MixWith(new Nameable("Me"));
// Now that it’s implemented, this
// will be true
isPerson = dynamic.LooksLike<IPerson>();
if (isPerson)
person = dynamic.CreateDuck<IPerson>();
// This will return “Me”
string name = person.Name;
// This will return ‘18’
int age = person.Age;

Categories