Inheriting object and auto populate - c#

When I want to extend an existing Object I create my own and use inherits clause, and works fantastic... problem is when I want to use this new Object instead of the original, the populate part is a "pain".
is there any AUTO POPULATE way of doing this?
Original Object: Customer
My Object: CustomerWithGroup
public class CustomerWithGroup : Customer
{
public CustomerWithGroup() { }
public string GroupName { get; set; }
public string Fullname
{
get
{
return string.Format("{0} {1} {2}", firstname, middlename, lastname).Replace(" ", " ");
}
}
}
and I'm populating it like this:
customerswithgroup = new List<CustomerWithGroup>();
string groupname;
foreach (Customer c in customers)
{
groupname = customergroup.Find(x => x.customer_group_id == c.group_id).customer_group_code;
customerswithgroups.Add(
new CustomerWithGroup {
GroupName = groupname,
created_at = c.created_at, customer_id = c.customer_id, default_billing = c.default_billing, default_shipping = c.default_shipping, email = c.email, firstname = c.firstname, group_id = c.group_id, increment_id = c.increment_id, lastname = c.lastname, middlename = c.middlename, password_hash = c.password_hash, prefix = c.prefix, store_id = c.store_id, suffix = c.suffix, taxvat = c.taxvat, updated_at = c.updated_at, website_id = c.website_id });
}
It's a bunch of code! and you can imagine doing this for really big objects!
Ins't there a way of telling, like
Hei object, please load all the base members from this Object!
newCG = new CustomerWithGroup().LoadFromBase(c);
newCG.groupName = "my group";
customerswithgroup.Add( newCG );
Is there any trick we can use?

No, there is no easy way. You could use reflection and write a bunch of code to do that, but it would be a lot of work.
In my opinion you should rethink your design. Inheritance is not a good solution in this case, composition here is better, like so:
public class CustomerWithGroups
{
public CustomerWithGroups(Customer c) { Customer = c; }
public Customer Customer { get; private set; }
public string GroupName { get; set; }
public string Fullname
{
get
{
return string.Format("{0} {1} {2}", Customer.firstname, Customer.middlename, Customer.lastname).Replace(" ", " ");
}
}
}

You cannot easily do this automatically.
You could make a constructor or method in the derived class that takes an instance of the base class and copies all of the properties. (You'd still need to write it by hand, but you'd only need to write it once)
If you really want to do it automatically, you could use reflection to loop through the properties and make an expression tree that copies them from an original.
However, the best way is to use a has-a relationship, making CustomerWithGroups not inherit Customer and instead have a read-only Customer property of type Customer.

Related

Passing parameters to a constructor, which are properties of an object class

I'm very new to C#, and the realm of programming. I've been carrying out some exercises in books and YouTube videos to wrap my head around many of these concepts.
Currently, I'm stuck on this issue. I have a small application for a Consignment Shop, and I was working on removing the hard coded sample data, and having the program read data from text files.
Here is my Vendor class:
public class Vendor
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Vendor(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
This essentially takes my .csv file of Vendors and pushes them into a string array, creates the object and fills it's properties with array values, then adds the item to a list of type Vendor. This method throws no errors.
private void ReadFromFile()
{
string line = "";
while ((line = myReader1.ReadLine()) != null)
{
string[] data = line.Split(',');
Vendor v = new Vendor(data[0], data[1]);
store.Vendors.Add(v);
}
}
When I try this same solution for adding Items to a list, I would like to pass in the "Owner" of the item, which is a property of type Vendor, located in my Items class. Since I couldn't get a working solution on passing an object as a parameter in constructor, I decided to stick with passing formal data types. I basically want to use the Vendor's properties of First Name & Last Name, and set those as the Item Owner's first and last name.
public class Item
{
public string Title { get; set; }
public decimal Price { get; set; }
public Vendor Owner { get; set; }
public Item(string title, decimal price, string fName, string lName)
{
Title = title;
Price = price;
Item.Owner.FirstName = fName; // this is what I want to do
Item.Owner.LastName = lName; // throws objref error
}
}
//Input file format: title,price,fname,lname
while ((line = myReader2.ReadLine()) != null)
{
string[] data2 = line.Split(',');
decimal price = decimal.Parse(data2[1]);
Item i = new Item(data2[0],price,data2[2],data2[3]);
store.Items.Add(i);
}
The strings make it into the array, but when I run the debugger and check my store.Items List, every property value is set except for Owner, which is null.
I know one solution could be to somehow combine fName+lName into one string, but I'm having a hard time understanding how my Item constructor needs to be set up in terms of which parameters it will accept. No matter what I try, the Oner property is never received a value, which causes the rest of my application to crash.
I've been working at this for a few hours, but I can't seem to come up with a working solution, or even a workaround to this scenario.
Any help is greatly appreciated.
Thanks!
I don't think your code even compiles, but what you want is this:
Owner = new Vendor(fName, lName);
This essentially creates a Vendor instance and assigns it to the Owner variable. Owner is otherwise uninitialized and null, that's why you get the exception.
instead of this:
Item.Owner.FirstName = fName; // this is what I want to do
Item.Owner.LastName = lName; // throws objref error
You have exception because Item.Owner is actually not created.
Fix it:
public Item(string title, decimal price, string fName, string lName)
{
Title = title;
Price = price;
Item.Owner = new Vendor(fName, lName);
}
Also: why do you write 'Item.Owner'? It isn't seemed to be static. Use just Owner.
In Java, if a class is a member of another class, you initialise it with new.
So in your constructor, you'd do the following:
public Item(string title, decimal price, string fName, string lName)
{
Title = title;
Price = price;
Owner = new Vendor(fName, lName);

C# - Print/write out/change a mutable list of objects, properties is in another class. (great answers)

Long time reader, first time poster. I'm hoping this is not an duplicate but the similar ones I've seen are all for other languages or complicated, which I hope this isn't. There should be a simple solution to help all beginners like myself.
I'm trying to make a function to simply print out objects created by the user that are put in a list of another class.
My class for Employee objects:
public int ID { get; set; }
public string FirstName { get; set; }
ect...
I made a print function(if it can be used):
public void PrintEmployee()
{
Console.WriteLine("\nID:{0}\nFull Name: {1} {2}\nSocial Security Number: {3}\nWage: {4}\n", ID, FirstName, LastName, SocialNumber, HourWage);
}
Constructor // turned out to be irrelevant but can help someone else doing a similar project
public Employee(int ID, string firstname, string lastname, string socialnumber, string hourwage)
{
ID = 0;
FirstName = firstname;
LastName = lastname;
SocialNumber = socialnumber;
HourWage = hourwage;
}
Registry class, with list and creating the objects: // turned out to be irrelevant but can help someone else doing a similar project.
public List<Employee> Accounts { get; set; }
public Registry()
{
Accounts = new List<Employee>();
}
public void CreateAccount()
{
var employee = new Employee(0, "", "", "", "");
Console.Write("Enter first name <Name>: ");
employee.FirstName = Console.ReadLine();
Console.Write("Enter last name <Name>: ");
employee.LastName = Console.ReadLine();
Console.Write("Enter Social Security Number<YYMMDD-XXXX>: ");
employee.SocialNumber = Console.ReadLine();
Console.Write("Enter wage <XXXkr/h>: ");
employee.HourWage = Console.ReadLine();
employee.ID = Accounts.Count + 1;
Accounts.Add(employee);
}
I want to have each Employee printed in my own format, but I started with trying to just have them printed in any way. After creating an Registry object in the main method and call the print function I get ConsoleApplicationName.Method in the console.
The function should be simple(we have just started learning)and I'm probably gonna be embarrassed but for the life of me I don't know how to make it work.
I have tried to put the Employee print method into Console.WriteLine but it complains about static/void, I changed all of the properties to static and/or created instances of them but that doesn't help. Would inheritance solve the problem?
I could get it to work by putting the list and the function inside the Employee class? I've been told that it's good practice to have classes and objects divided after what they are, do few things but do them well. Somewhere I need to define how each Employee should be printed but I don't know where.
The method in Registry I can't get to work, I've tried:
public void PrintRegistry() //nr1
{
Accounts.ForEach(employee => Console.Write("{0}\n", employee));
}
> foreach(Employee employee in Accounts) // nr2
> {
> Console.WriteLine(employee);
> }
Accounts.ForEach(Console.WriteLine); // nr3
My gratitude for any help, if I need to spend a few hours to fully understand your reply I'll gladly put in the work.
You will need your own implementation of ToString in your Employee class. You just need to override it and put your code of PrintEmployee in the new method.
Just to make it clear what I mean I give you a sample on how the override should look like:
public override string ToString()
{
return string.Format("ID:{0}{5}Full Name: {1} {2}{5}Social Security Number: {3}{5}Wage: {4}{5}", ID, FirstName, LastName, SocialNumber, HourWage, Environment.NewLine);
}
To give you a little background information: every class or struct in c# inherits from the Object class. Per default the Object class already has an implementation of ToString. This basic implementation would only print out namespace + class name of your Employee class. But with the above override you could simply write something like the following and get your wished output:
var employee = new Employee { Firstname = "Happy", Lastname = "Coder", ... }
Console.WriteLine(employee);
Here's a simple solution
private void PrintRegistry()
{
foreach(Employee employee in Accounts)
{
Console.WriteLine("\nID:{0}\nFull Name: {1} {2}\nSocial Security Number: {3}\nWage: {4}\n", employee.ID, employee.FirstName, employee.LastName, employee.SocialNumber, employee.HourWage);
}
}
Or if the "PrintEmployee" PROCEDURE (not function as it doesn't return a value) is in the "Employee" class.
private void PrintRegistry()
{
foreach(Employee employee in Accounts)
{
employee.PrintEmployee();
}
}

List in a List (Associations)

Trying to further my own understanding, I'm replication a simple database - and having trouble understanding the following;
I have 2 classes Town and People. A town owns many instances of People and are set like this;
public class Town
{
List<People> collectionOfPeople;
public string townName { get; set; }
public Town()
{
townName = "Cardiff";
collectionOfPeople = new List<People>();
collectionOfPeople.Add(new People("Daniel Smith"));
}
}
public class People
{
public string name { get; set; }
public People(string tmp_name)
{
name = tmp_name;
}
}
Assuming what I've done is correct, Town has 1 value (Cardiff) and People also has one (Daniel Smith) or .. Daniel lives in Cardiff.
I am trying to display the names of People living within the Town.. to later cycle through them. (** = problem I think)
private List<Town> townList;
private List<Town.People> peopleList; **
private void ShowData()
{
// Add to Text Box based on current Record
txt_town.Text = townList[0]).townName;
txt_name.Text = peopleList[0].name; **
}
Here are my changes. Provide public access modifier for collectionOfPeople in Town class.
public class Town
{
public List<People> collectionOfPeople;
public string townName { get; set; }
}
After that, you can access People instance within Town. Something like this:
private List<Town> townList = new List<Town>();
private void ShowData()
{
// Add to Text Box based on current Record
txt_town.Text = townList[0].townName;
txt_name.Text = townList[0].collectionOfPeople[0].name
}
You haven't said what, if any, error messages you're getting but I believe in order to have
Town.People
you need to create a property of your Town class called People. I don't see that in your code.
Also, there's an extra parenthesis in your line:
txt_town.Text = townList[0].townName: //no ) after [0]

comparing objects and returning list

I have a class definition that looks like this:
public class MyObjectModel
{
public int ObjectID { get; set; }
//for when the user's data is split in 2 fields
public string FirstName { get; set; }
public string LastName { get; set; }
//for when the user's data is all in one field
public string FirstLastName { get; set; }
}
I have a list of these MyObjectModel and I want to sort them by name with a custom sort process because that involves checking if the data contains a LastName (in this case sort using the LastName) or just FirstLastName (in this case I'm going to break the string and sort on the second term, if there's one, or just the whole string if there's only one word.)
I'm not sure on two things:
should I use IComparer or IComparable?
Once it determines the order of the sort (I can do that), how do I make it so that the output of the method is a list of ints representing ObjectID.
Use Linq:
List<MyObjectModel> objects = new List<MyObjectModel>();
List<int> ids = objects.OrderBy(o => FunctionWhichReturnsNameForSort(o)).Select(o => o.ObjectID).ToList();
FunctionWhichReturnsNameForSort can be implemented in another class, or an extension, or as a member.
// should be in a static helper class
public static string NameForSort(this MyObjectModel obj)
{
if (!string.IsNullOrEmpty(obj.LastName)) return obj.LastName;
return obj.FirstLastName.Split(... // your splitting logic goes here
}
var ids = objects.OrderBy(o => o.NameForSort()).Select(o => o.ObjectID).ToList();
When you really need this strange double solution then you will run into this and similar problems more often. As a more general solution, consider putting the business logic for names in a few read-only properties:
//for when the user's data is split in 2 fields
public string FirstName { get; set; }
public string LastName { get; set; }
//for when the user's data is all in one field
public string FirstLastName { get; set; }
public string FullName
{
get { ... } // pick from LastName, FirstName, FirstLastName
}
public string SortName
{
get { ... } // pick from LastName, FirstLastName
}
Once it determines the order of the sort (I can do that), how do I make it so that the output of the method is a list of ints representing ObjectID
result = MyObjectList
.OrderBy(m => m.SortName) // sort on SortName
.Select(m => m.ObjectID) // select the Id
.ToList();
If this sorting is specific to one use case, it can be achieved using LINQ:
var sortedIds = models.OrderBy(SecondName).Select(m => m.ObjectId).ToList();
private static string SecondName(MyObjectModel model)
{
if (!string.IsNullOrWhitespace(model.LastName)) return model.LastName;
return model.FirstLastName.Split(' ').Last();
}
While you can use LINQ, as others have suggested, that would involve creating a brand new list, not mutating the existing list. That may or may not be preferable. If you want to sort the list itself that's easy enough too:
List<string> list = new List<string>(){"a","b","c"};
list.Sort((a,b)=> a.CompareTo(b));
Just take your list, call Sort, and pass in a lambda that takes two items and returns an integer indicating which is greater. In your case, just call some method on a and b to get a string and then use CompareTo or string.Compare on those two strings.

Constructing an object graph from a flat DTO using visitor pattern

I've written myself a nice simple little domain model, with an object graph that looks like this:
-- Customer
-- Name : Name
-- Account : CustomerAccount
-- HomeAddress : PostalAddress
-- InvoiceAddress : PostalAddress
-- HomePhoneNumber : TelephoneNumber
-- WorkPhoneNumber : TelephoneNumber
-- MobilePhoneNumber : TelephoneNumber
-- EmailAddress : EmailAddress
This structure is completely at odds with the legacy database I'm having to work with, so I've defined a flat DTO which contains the data for each element in the customer graph - I have views and stored procedures in the database which allow me to interact with the data using this flat structure in both directions, this all works fine & dandy :)
Flattening the domain model into a DTO for insert/update is straightfoward, but what I'm having trouble with is taking a DTO and creating the domain model from it... my first thought was to implement a visitor which would visit each element in the customer graph, and inject values from the DTO as necessary, something a bit like this:
class CustomerVisitor
{
public CustomerVisitor(CustomerDTO data) {...}
private CustomerDTO Data;
public void VisitCustomer(Customer customer)
{
customer.SomeValue = this.Data.SomeValue;
}
public void VisitName(Name name)
{
name.Title = this.Data.NameTitle;
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
}
// ... and so on for HomeAddress, EmailAddress etc...
}
That's the theory and it seems like a sound idea when it's laid out simply like that :)
But for this to work the entire object graph would need to be constructed before the visitor erm, visited, otherwise I'd get NRE's left right and centre.
What I want to be able to do is let the visitor assign objects to the graph as it visits each element, with the goal being to utilize the Special Case pattern for objects where data is missing in the DTO, eg.
public void VisitMobilePhoneNumber(out TelephoneNumber mobileNumber)
{
if (this.Data.MobileNumberValue != null)
{
mobileNumber = new TelephoneNumber
{
Value = this.Data.MobileNumberValue,
// ...
};
}
else
{
// Assign the missing number special case...
mobileNumber = SpecialCases.MissingTelephoneNumber.Instance;
}
}
Which I honestly thought would work, but the C# throws me an error on:
myVisitor.VisitHomePhone(out customer.HomePhoneNumber);
Since you can't pass ref/out parameters in this way :(
So I'm left with visiting independent elements and reconstructing the graph when its done:
Customer customer;
TelephoneNumber homePhone;
EmailAddress email;
// ...
myVisitor.VisitCustomer(out customer);
myVisitor.VisitHomePhone(out homePhone);
myVisitor.VisitEmail(out email);
// ...
customer.HomePhoneNumber = homePhone;
customer.EmailAddress = email;
// ...
At this point I'm aware that I'm quite far away from the Visitor Pattern and am much closer to a Factory, and I'm starting to wonder whether I approached this thing wrong from the start..
Has anyone else run into a problem like this? How did you overcome it? Are there any design patterns which are well suited to this scenario?
Sorry for posting such a looong question, and well done for reading this far :)
EDIT In response to the helpful answers from Florian Greinacher and gjvdkamp, I settled on a relatively simple factory implementation that looks like this:
class CustomerFactory
{
private CustomerDTO Data { get; set; }
public CustomerFactory(CustomerDTO data) { ... }
public Customer CreateCustomer()
{
var customer = new Customer();
customer.BeginInit();
customer.SomeFoo = this.Data.SomeFoo;
customer.SomeBar = this.Data.SomeBar
// other properties...
customer.Name = this.CreateName();
customer.Account = this.CreateAccount();
// other components...
customer.EndInit();
return customer;
}
private Name CreateName()
{
var name = new Name();
name.BeginInit();
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
// ...
name.EndInit();
return name;
}
// Methods for all other components...
}
I then wrote a ModelMediator class to handle interaction between the data layer and the domain model...
class ModelMediator
{
public Customer SelectCustomer(Int32 key)
{
// Use a table gateway to get a customer DTO..
// Use the CustomerFactory to construct the domain model...
}
public void SaveCustomer(Customer c)
{
// Use a customer visitor to scan for changes in the domain model...
// Use a table gateway to persist the data...
}
}
I think you are really over-complicating things here. Just use a factory method and let your domain objects clearly state on which other domain objects they depend.
class Customer
{
private readonly Name name;
private readonly PostalAddress homeAddress;
public Customer(Name name, PostalAddress homeAddress, ...)
{
this.name = name;
this.homeAddress = homeAddress;
...
}
}
class CustomerFactory
{
Customer Create(CustomerDTO customerDTO)
{
return new Customer(new Name(...), new PostalAdress(...));
}
}
If you need to take a dependency from Customer to CustomerDTO pass the DTO as additional argument to the constructor, probably wrapped in an additional abstraction.
This way things will keep clean, testable and easy to understand.
I don't think i would go with a visitor. That would be appropriate if you don't know at design time, what operations you need to perform on it later, so you open up the class to allow for others to write visitors that implement that logic. Or there are so many things that you need to do on it that you don't want to clutter your class with this.
What you want to do here is create an instance of a class from a DTO. Since the structure of the class and the DTO are closely linked (you do your mapping in the DB, I assume you handle all mapping issues on that side and have a DTO format that maps directly to the structure of your customer), you know at design time what you need to. There's no need for much flexibility. (You want to be robust though, that the code can handle changes to the DTO, like new fields, without throwing exceptions)
Basically you want to construct a Customer from a snippet of a DTO. What format do you have, just XML or something else?
I think I would just go for a constructor that accepts the DTO and returns a Customer (example for XML:)
class Customer {
public Customer(XmlNode sourceNode) {
// logic goes here
}
}
The Customer class can 'wrap around' an instance of the DTO and 'become one'. This allows you to very naturally project an instance of your DTO into a customer instance:
var c = new Customer(xCustomerNode)
This handles the high level pattern choice. Do you agree so far?
Here's a stab at the specific issue you mention with trying to pass properties 'by ref'.I do see how DRY and KISS can be at odds there, but I would try not to overthink it. A pretty straight forward solution could fix that.
So for the PostalAddress, it would have it's own constructor too, just like the Customer itself:
public PostalAddress(XmlNode sourceNode){
// here it reads the content into a PostalAddress
}
on the customer:
var adr = new PostalAddress(xAddressNode);
The problem I see here is, where do you put the code that figures out if this if the InvoiceAddress or the HomeAddress? This does not belong in the constructor of the PostalAddress, because there could be other uses for the PostalAddress later, you don't want to hardcode it in the PostalAddress class.
So that task should be handled in the Customer class. This is where he usage of the PostalAddress is determined. It needs to be able to tell from the returned Address what type of address it is. I guess the simplest approach would be to just add a property on PostalAddress that tells us:
public class PostalAddress{
public string AdressUsage{get;set;} // this gets set in the constructor
}
and in the DTO just specify it:
<PostalAddress usage="HomeAddress" city="Amsterdam" street="Dam"/>
Then you can look at it in the Customer class and 'stick it' in the right property:
var adr = new PostalAddress(xAddressNode);
switch(adr.AddressUsage){
case "HomeAddress": this.HomeAddress = adr; break;
case "PostalAddress": this.PostalAddress = adr; break;
default: throw new Exception("Unknown address usage");
}
A simple attribute that tells the Customer what type of address it is would be enough I guess.
How does it sound so far? Code below puts it all together.
class Customer {
public Customer(XmlNode sourceNode) {
// loop over attributes to get the simple stuff out
foreach (XmlAttribute att in sourceNode.Attributes) {
// assign simpel stuff
}
// loop over child nodes and extract info
foreach (XmlNode childNode in sourceNode.ChildNodes) {
switch (childNode.Name) {
case "PostalAddress": // here we find an address, so handle that
var adr = new PostalAddress(childNode);
switch (adr.AddressUsage) { // now find out what address we just got and assign appropriately
case "HomeAddress": this.HomeAddress = adr; break;
case "InvoiceAddress": this.InvoiceAddress = adr; break;
default: throw new Exception("Unknown address usage");
}
break;
// other stuff like phone numbers can be handeled the same way
default: break;
}
}
}
PostalAddress HomeAddress { get; private set; }
PostalAddress InvoiceAddress { get; private set; }
Name Name { get; private set; }
}
class PostalAddress {
public PostalAddress(XmlNode sourceNode) {
foreach (XmlAttribute att in sourceNode.Attributes) {
switch (att.Name) {
case "AddressUsage": this.AddressUsage = att.Value; break;
// other properties go here...
}
}
}
public string AddressUsage { get; set; }
}
class Name {
public string First { get; set; }
public string Middle { get; set; }
public string Last { get; set; }
}
and a snippet of XML. You haven't said anything about your DTO format, would work for other formats too.
<Customer>
<PostalAddress addressUsage="HomeAddress" city="Heresville" street="Janestreet" number="5"/>
<PostalAddress addressUsage="InvoiceAddress" city="Theresville" street="Hankstreet" number="10"/>
</Customer>
Regards,
Gert-Jan
For doing conversions between a model class and a DTO, my preference is to do one of four things:
a. use an implicit conversion operator (especially when dealing json-to-dotnet transitions).
public class Car
{
public Color Color {get; set;}
public int NumberOfDoors {get; set;}
}
public class CarJson
{
public string color {get; set;}
public string numberOfDoors { get; set; }
public static implicit operator Car(CarJson json)
{
return new Car
{
Color = (Color) Enum.Parse(typeof(Color), json.color),
NumberOfDoors = Convert.ToInt32(json.numberOfDoors)
};
}
}
and then usage is
Car car = Json.Decode<CarJson>(inputString)
or more simply
var carJson = new CarJson {color = "red", numberOfDoors = "2"};
Car car = carJson;
voila, instant conversion :)
http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx
b. Use linq projection to change the shape of the data
IQueryable<Car> cars = CarRepository.GetCars();
cars.Select( car =>
new
{
numberOfDoors = car.NumberOfDoors.ToString(),
color = car.Color.ToString()
} );
c. Use some combination of the two
d. Define an extension method (that could also be used in the linq projection)
public static class ConversionExtensions
{
public static CarJson ToCarJson(this Car car)
{
return new CarJson {...};
}
}
CarRepository.GetCars().Select(car => car.ToCarJson());
You could take the approch I described here: convert a flat database resultset into hierarchical object collection in C#
The idea behind is to read an object, like Customer and put it into a Dictionary. When reading the data for e.g. CustomerAccount, you can now take the Customer from the Dictionary and add the Customer Account to the customer.
You'll have only one iteration over all data to build your object graph.

Categories

Resources