Best way to pass control values from form to separate class - c#

I have a WinForms application that creates a huge, custom textfile. To do this requires the user to configure dozens of controls on the main form and then click a Submit button. What is the best way to pass all those control values to my Generator class? The problem is I'm ending up with 20+ parameters to pass to a Generate() method. I can group some of those into Config objects (i.e. the date/time controls can be passed into a DateTimeConfig object) and then pass these config objects into the Generate() method to minimize the number of parameters needed, but it still feels like there must be a better way. Any ideas?
EDIT: Thank you for your responses, but I was hoping for something other than a configuration object (as that's what my OP mentioned). I guess what I was hoping for is some way to serialize the values of all the controls automatically, without having to build a custom object and then modify that everytime a control changes or gets added/removed.

Why not create a custom object class as container of your data and then pass the istance of this class to the Generator method as parameter?

Look into Model Driven Development, where the parameters are grouped into business objects or data transfer objects (DTOs). This is a more intuitive way to group parameters than by datetime, etc.
If you place those model objects in a separate project, you can pass those objects around the solution (from one method to another and one project to another) without having to serialize them or mess with long parameter list ordering. You can even nest model objects inside other model objects.
In this example, notice you only have to change parameters in the Person object or the Address object and you never have to serialize or map anything:
// this is my business model object
public class Person
{
public int PersonId { get; set; }
public string PersonName { get; set; }
// notice the Address object nested in the Person class
public Address HomeAddress { get; set; }
}
// this is another class that lives inside the person class
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
In one class you could have this method that receives a person with an address and passes the person to another class's SavePerson class:
public void ProcessPerson(Person person)
{
person.PersonName = "Robert";
Address address = new Address();
address.City = "Austin";
person.Address = address;
SavePerson(person);
}
Some other class (even in another project) can take that person and pass it to the persistence layer:
public void SavePerson(Person person)
{
database.Save(person);
}
So if I want to add a State to the person I just change the Address class and I'm all done in one step, I don't have to add the state field to all the method parameter lists:
public class Address
{
public string Street { get; set; }
public string City { get; set; }
// this is the new property
public string State { get; set; }
}

Create a model object that has a value for each control.
So let's say you have a form that has a first name, last name, birthday and salary.
Your model would be
public class SalaryModel
{
public string FirstName {get; set;}
public string LastName {get; set;}
public DateTime Birthday {get; set;}
public decimal Salary {get; set;}
}
Then when submit is clicked, you create this object and pass it to your generator class.
One reason for this is your generator needs to know NOTHING about the control other than it's value. That is a generator class shouldn't be concerned about .IsVisible() or .TabOrder or any of that other junk. It only cares about what the value is.

Create a container class. Keep an instance of it common for your main form and whatever form is going to use it/pass it to the other form or class as parameter.
Take all the values from your form and fill the container class. Usually a container/entity class would be full of properties and will have a very few methods.

Move you Generate() Method to a class and utilize the class properties. You can also then support data binding from you form.
Ex.
Take this
Generate (List<int> x, bool Opt1);
to This
public class Generate
{
List<int> Ids {get;set;}
bool Opt1 {get;set;}
bool Generate();
}

Related

Undestanding CRUD with Composition

I pretty want to understand how to organize my code. Let's say i have this class called "Brand" which has a "Product" object:
public class Brand {
public int ID { get; set; }
public int name { get; set; }
public Product product { get; set; }
public void add(Brand brand)
{
// Database logic
}
}
And this class called product
public class Product {
public int ID { get; set; }
public int name { get; set; }
}
What i want to know is should i have a method AddProduct inside product class or should the method be on the top class "Brand". That is my confusion.
In order to make better sense of this, think about separation of concerns and single responsiblity. The answer in this post is a nice way of putting this.
Right now you have an object called Brand that contains a method Add and some properties related to being a Brand object. This means that not only is the Brand charged with managing itself, it's also charged with managing it's own interaction with the database. You are fixing to have a similar coupling between the Product and the database as well. Then what happens when you have a collection of brands, and you realize each brand should have a collection of products, and they all have Database logic strewn throughout? Then, say you notice that each Product needs a list of ingredients, so you have to add that, so the ingredients need database logic, etc. etc. You can see this gets very confusing very quickly.
So really, you should have a third class that is responsible for managing database objects, and that class will have methods to call that take your Brand and Product objects as parameters and interact with the database internally. Now you have abstracted your database logic away from your Brand and Product logic, so the Database class can do what it's built for and no more, and the Brand and Class objects can exist as defined wrappers for related data and no more. Everything is now divided so each class represents a single simple concept. Brand class exists to represent brand data. Database class exists to interact with the database.
I'm sure you get the concept and you may have seen this a thousand times already, but thinking like this will help you spot what needs to change and find much simpler, cleaner, more maintainable solutions.
The way you declared the product is using the C# Auto Property.
First of all, you should ask yourself do you need the product to be visible as public member, or you want to encapsulate the logic of setting the product.
If the answer is that you want to want the Product to be able to set outside, then there is no need to declare any additional method:
public class Brand
{
public int Id { get; set; }
public string Name { get; set; }
public IProduct Product { get; set; }
}
public static void Main(string[] args)
{
var brand = new Brand
{
Id = 1,
Name = "Name",
Product = new Product()
};
}
However, if you want to encapsulate the way you set the product then consider using either Composition or Aggregation approaches:
public class Brand
{
private int _id;
public string _name;
private readonly IProduct _product;
public Brand(IProduct product, int id, string name )
{
_product = product;
_id = id;
_name = name;
}
}
public static void Main(string[] args)
{
var brand = new Brand(new Product(), 1, "prd");
}
Note: if you still want to be able to set the product after object declaration, consider a different name for the method, like SetProduct or something with close meaning, because AddProduct means that you are dealing with the collection of Products.

Advice on class structure

I have a class Student which needs to be persisted in the database. I have methods that create and update these students (CreateStudent, UpdateStudent) and right now, the structure of this Student class is:
public class Student
{
public int ID { get; set; }
public string FirstName { get; set; }
}
Now what I am thinking is my CreateStudent accepts a Student object:
public int CreateStudent(Student newStudent);
However, since this student is new, the ID wouldn't be persisted (or shouldn't be persisted) to the database. But it seems unclear to the user of the method that this is how it works. For example, I used CreateStudent but passed a Student.ID of 6, the CreateStudent method would ignore the ID since this is creating a student. However, I am trying to find something that is clearer. What I want to try now is separating the ID to an interface which would only be available when a Student is already existing in the database. Sort of like this:
public IEntity
{
int ID { get; set; }
}
public interface IUnknownStudent
{
string FirstName { get; set; }
}
public interface IStudent : IUnknownStudent, IEntity
{
}
Then when using CreateStudent, I pass a IUnknownStudent (no ID).
Only when retrieving or updating will I use the implementation with an ID. But I am not sure if this has any problems since its the first time I'm trying it, and I was wondering if the experienced guys here can give some advice about this.
EDIT:
CreateStudent() is on a separate class, StudentLogic.
One thing I see is that you would probably want a separate class for StudentData in which you have the method
public int createStudent(Student s){
//TODO: Implement method here
}
The reason that I believe that you should have another class to house the method for createStudent is because that you shouldn't have to instantiate a Student to access the createStudent method. Think of it this way, say I create my class Student
public class Student
{
public string firstName { get; set; }
//rest of class
}
When I go to create a Student using the createStudent method inside the class, I would have to say this:
Student s = new Student();
s.createStudent(s);
And that is not really how we want to have to create things, right? That code would be hard to read and understand if you want to keep this updated.
I agree that you'd want to have the ID implemented as a separate class or interface, depending on what you need, and you might want to have a default value for "ID" in the event of an Unknown New Student being created. This way, when you return the ID of the new Student, it's always the same until the user input the new ID for the Student or the next ID was automatically selected. The main thing that I suggest is using a StudentData class to house the createStudent method and house your main function, if you have one. This way, you're using more of an MVC(Model-View-Controller) style of Development, with a Student and their ID as the Model and the View and Controller being handled by the StudentData class. It's just an easy way to structure things once you understand it.

Nested Properties / Classes

I would like to be able to having a class with properties, but have some way of "namespacing" the properties.
In the end I would like to have a class:
Class Employee
{
public string Name {get; set;}
private class/namespace/something HomeAddress
{
public string Street {get; set;}
}
}
I would like to be able to go:
Employee emp = new Employee();
emp.Name = "Joe";
emp.HomeAddress.Street = "Best St.";
Is this even possible? (or best practice, what is best practice anyway for something like that?) I know I can create separate classes, initialize them in the Employee Constructor and go from there...
But I would like to hide the nested classes since they will only be used in the Employee class. I would like to avoid having this:
HomeAddress home = new HomeAddress();
home.Street = "Worst St.";
I would like to hide this from the intellisense list and not have it be something that can be created on its own so only the Employee class is visible for someone to create since these sub helper classes will only be used inside other objects and never on their own.
There is another example from another question:
class Fruit{
public void eat(){
MessageBox.Show("Fruit eaten");
}
public string color = "red";
//you have declared the class but you havent used this class
public class physicalProperties{
public int height = 3;
}
//create a property here of type PhysicalProperties
public physicalProperties physical;
}
But this isn't quite what I was after either since physicalProperties is public. You would still be able to:
Fruit.physicalProperties fruitProp = new Fruit.physicalProperties();
And use this outside of the Fruit class.
I have a feeling I am chasing after something that I am never going to find, but I am curious if anyone else has ever had to need to do something like this? It seems when you build out an application you end up with reams of objects in the intellisense list, of which some are landmines since if someone saw HomeAddress they might think it is useful for something. If only Employee showed up in the intellisense list then they would be on the right track from the start, creating the Employee object and then modifying everything associated with that employee.
Having all the supporting junk in the same intellisense list as the main objects you are supposed to be working with seems to add noise and distraction, especially if the person doing the coding isn't familiar with your library. It seems to me that this way would be a subtle guide as to what you should be creating, and once you create it how you should be manipulating it...
To prevent the creating of an address, I would do the following. The interface is public, but the implementing nested class is private.
public class Employee {
#region Constructor(s)
public Employee() {
HomeAddress = new Address();
}
#endregion
#region Properties
public string Name { get; set;}
public IAddress HomeAddress { get; private set; }
#endregion
#region Nested
public interface IAddress {
string Street { get; set; }
}
private class Address: IAddress {
public string Street { get; set;}
}
#endregion
}
After reading #Moeri's answer, you could also create the instance lazily instead of in the constructor.
What about nesting the Address class in the Employee class and automatically initializing it lazily if needed.
public class Employee
{
public string Name {get; set;}
private Address _homeAddress;
// only contains a getter, which auto-initializes the value to avoid NullReferenceException
// this auto initialization is also useful to declutter your constructors
public Address HomeAddress
{
get { return _homeAddress ?? (_homeAddress = new Address()); }
}
public class Address
{
// only classes from the same assembly can create addresses
internal Address() {}
public string Street {get; set;}
}
}
You can't have "nested properties" without specifying a type for each nest level. Furthermore, the type of each level will have to be accessible to the caller (public).
But you can avoid the need for this:
HomeAddress home = new HomeAddress();
home.Street = "Worst St.";
By creating the new HomeAddress from within the Employee constructor:
public Employee()
{
this.HomeAddress = new HomeAddress();
}
public HomeAddress HomeAddress
{
get;
private set;
}
No one can assign a new HomeAddress to the property, but they can change the values of HomeAddress.
One other thing to remember is that if you have a nested class Employee.HomeAddress, the property cannot be of the same name.

Simple calculated property and DTO

I have a WCF service which exposes its interface with DTOs. I have an entity class MyClass which has two properties SimpleProperty1 and SimpleProperty2. There is a calculated property in this class named CalculatedProperty1 which uses the above two properties in calculating its value. I have a MyClassDTO dto class which has only the two simple properties.
In the UI, where a MyClassDTO object is being modified, I want the user to see the value of CalculatedProperty on the fly. However, as according to my understanding DTOs should not have any logic embedded in them. And it seems a bit of a waste to implement a function in the web service to get the calculated value of the property in such a simple scenario. How should I go about getting this done? What are the standard approaches of doing this? I see that the generated classes from the WCF service are defined as partial classes. Is it there to handle this sort of scenario?
you can use extension method to show the calculated property
public class MyClassDTO
{
public string P1 { get; set; }
public string P2 { get; set; }
}
public static class MyClassDtoExtension
{
public static string ToCalculatedProperty(this MyClassDTO obj)
{
return obj.P1 + obj.P2;
}
}
// usage
var d = new MyClassDTO(){P1 = "1",P2 = "2"};
d.ToCalculatedProperty();

Entity objects with helper properties

In my domain model I have an Entity object that looks as follows:
public class Group
{
public int idGroup { get; set; }
public string Description { get; set; }
}
I have a repository for this object:
public class GroupRepository : IGroupRepository
{
public Group LoadGroup(int idGroup)
{
//imitation of SQL data reader
Group g = new Group();
g.idGroup = Convert.ToInt32(r["idTipoGrupo"]);
g.Description = Convert.ToString(r["Descricao"]);
return g;
}
}
But now I need to get some extra information from data store about Group objects through a new function in my created repository, here are the fields I need:
public bool HasChildGroups { get; set; }
public int ChildGroupsCount { get; set; }
public bool HasDeals { get; set; }
public int DealsCount { get; set; }
These properties look to me like a "service" or "helper" properties and I don't plan to use them everywhere in my application, only few times, but I need them. The simplest thing I could think of is that I added these "service" properties to my Group object and created a method in my repository that populates them. But I consider doing this wrong, as it is the Entity and I don't need them in here. So where should I keep such "service" objects? Do I have to create a new class that inherits from Group like this:
public class GroupHelper : Group
{
public bool HasChildGroups { get; set; }
public int ChildGroupsCount { get; set; }
public bool HasDeals { get; set; }
public int DealsCount { get; set; }
}
Or should I consider using some Data Transfer Objects?
How would you solve this problem?
Any help appreciated.
The first question to ask is how the state of the proposed GroupHelper object is managed. Attributes such as HasChildGroups seems like they would be altered as a result of behaviors invoked on a Group entity. If so, then they should be first class entities in your domain model, perhaps event part of the group entity itself. If the properties are managed outside of your domain model then you can just query that data as you would any other external data source. I would have this be a standalone object, perhaps called something like GroupInfo not extending Group itself.
What seems to be the issue here is that you have query requirements that aren't in alignment with the shape of your entities. In that case you have the flexibility to decouple your read-models from your domain models. Read-models are intended to fulfill query requirements and your domain models are intended to host behavior associated with your domain.
HasChildGroups [...] look to me like a "service" or "helper" properties [...] But I consider doing this wrong, as it is the Entity and I don't need them in here.
If you concider your Group object to be a data access object and you have a separate model for, say, viewdata, you're right.
But this may also be a fat class, providing in view-specific and database-specific code. It's not plain wrong.
You could indeed create a GroupDTO class that provides the properties you require in the application but not for the data access, to separate concerns.

Categories