How can I combine properties from different classes [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
Let's say I have two classes like
public partial class dbUserDetails
{
public int Id { get; set; }
[AllowHtml]
public string Bio { get; set; }
//some properties
}
public partial class SomeOtherClass
{
[DisplayName("Profile Picture (max. 2MB)")]
public HttpPostedFileBase File { get; set; }
//some properties
}
And I want to combine some properties like
public class Settings
{
//HttpPostedFileBase File
//public string Bio { get; set; }
}
Razor:
#model myAppp.Models.Settings
#Html.EditorFor(m => m.Bio)
#Html.EditorFor(m => m.File)
Is it possible to use in this way? I know something about interface and partial. But I dont know how i will exactly figure out.

For this to work you would have to pass the information from dbUserDetails and SomeOtherClass to you Settings class. The easiest way for this would be to simply create the Settings class with instances of the two other classes and make them available as properties:
public class Settings{
private dbUserDetails userDetails;
public dbUserDetails UserDetails {
return userDetails;
}
private SomeOtherClass someOtherInfo;
public SomeOtherClass SomeOtherInfo{
return someOtherInfo;
}
public Settings(dbUserDetails user, SomeOtherInfo other) {
userDetails = user;
someOtherInfo = other;
}
}
Now you can access them this way: m => m.UserDetails.Bio
I did it via this way of accessing and not the way you mentioned before (direct access) because you would otherwise have the property duplicated at two positions. I would only do that if there was a good reason for this.
Edit:
For some clarification on why I chose the above written code:
Storing the dbUserDetails and SomeOtherClass objects in Settings does not create significant memory overhead at this point. All their properties should be accessible using Settings to they have to be stored somewhere. Therefore I decided to just leave them where they are.
A memory problem would only occur if the two classes stored more information than you want to make accessible and are not used anymore so that they could be deleted. In this case it would make sense to actually copy the information like this:
public class Settings{
private string bio;
public string Bio {
return bio;
}
/*...*/
public Settings(dbUserDetails user, SomeOtherInfo other)
{
bio = user.Bio;
/*...*/
}
}
If you do not delete the two aforementioned objects when doing this, you store the information twice (=> memory overhead). This is worse than just storing references to the objects.
Another option would be this:
public class Settings{
private dbUserDetails userDetails;
public string Bio {
return userDetails.Bio;
}
public Settings(dbUserDetails user, SomeOtherInfo other)
{
userDetails = user;
/*...*/
}
}
This would be the same idea as the first one but with direct access to the properties. It would work as well but lead to more code duplication. Each new property in the sub objects would lead to a property in Settings

Related

Modeling JSON message [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm using a web service with this request format:
{
"type":"LogonReq",
"id":"b43b301c-5216-4254-b3fc-cc863d4d6652",
"date":"Wed, 16 Aug 2017 17:35:34 UTC",
"parameters":[
{
"userName":"user",
"password":"password"
}
]
}
Even though every message in the API requires only 1 set of parameters, the API still requires "parameters" to be an array.
Is it better practice to have the caller create the list or to create the list in the MessageBase constructor, or something altogether different ?
Which way would satisfy an OOP purist code reviewer?
public class MessageBase<T>
{
public MessageBase() { this.parameters = new List<T>(); }
public string type { get; set; }
public string id { get; set; }
public string date { get; set; }
public List<T> parameters { get; set; }
}
public class LogonMessage{
public string userName { get; set; }
public string password { get; set; }
}
var logon = new MessageBase<LogonMessage>()
{
date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss UTC"),
id = Guid.NewGuid().ToString(),
type = "LogonReq",
};
logon.parameters.Add(new LogonMessage() { userName = "user", password = "password" });
or
public class MessageBase<T>
{
public string type { get; set; }
public string id { get; set; }
public string date { get; set; }
public List<T> parameters { get; set; }
}
public class LogonMessage{
public string userName { get; set; }
public string password { get; set; }
}
var logon = new MessageBase<LogonMessage>()
{
date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss UTC"),
id = Guid.NewGuid().ToString(),
type = "LogonReq",
parameters = new List<LogonMessage>() { new LogonMessage() { userName = "user", password = "password" } }
};
You will probably find many interesting opinions and answers to this. I can only give you mine based on my experience.
I myself would probably initialize the list within the constructor
However, since you are trying to get a good idea around the phylosophy of coding, here are some things to consider :
1) Does the MessageBase object make sense or is it useful with a NULL list? Is there any scenario where I want this list as null?
2) Actually, I would expect an OOP purist to say that you should not expose the "parameters" as a List. By exposing the object as a property, someone can do this:
login.parameters.Add()
Or this
logon.parameters = anotherListOfMine
In a way it does break encapsulation. You could make the list property read only (ie, with a protected/private setter) but "clients" of this class will still be able to access all properties and methods of the List and modify/handle them.
Now, you have to expose this in some way as you will be serializing/deserializing into JSON, so that poses a problem! Maybe you can have a private/protected List field and expose the values through a readonly property that exposes an IEnumerable and behind the scenes, you are doing:
get { return myPrivateList.ToArray(); }
3) But again, do you really win that much? Your next question should be "Who is my client?" If you are exposing this class to other developers, or is part of a framework, you might want to apply something like my point number 2, and limit the exposure. If this is internal to your application and your team maybe you should be pragmatic and simply expose the List as you are doing right now.
4) Alternatively, while still making it open, you could instead have a property of type IEnumerable so you can pass in any type.
5) Another option is to expose your list because you need to serialize it, but make it readonly. Have instead different methods, or non-serializable properties, of username and password. If these parameters are always the same that is. I am thinking this might not be your case.
I think I could go on and on this. I will stop here before you hit the downvote button :).

Handling extra data to store for each model attribute [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am working on an application where I want the user to be able to enter notes associated to any input field. For example, a user may type in a value for a field named Price, and add a note next to it to specify that it is negotiable under certain conditions.
The solutions I have considered are:
Creating two attributes for each field (e.g. Price and PriceNote)
Creating a new class (e.g. Field) containing a Value and a Note, then changing all model properties to that Field type.
There are downsides to both of these solutions, though. Creating additional attributes would bloat the code and make modifications awkward, while creating an extra class would require typecasting field values constantly and handling editors/displays manually in the views.
Is there a better, more elegant solution?
Not sure what the backend looks like, but you could create a object that looks like this:
{ProductId: 123,
ProductName:'Widget',
Price:200.00,
minQuantity: 10,
Comments:[
Price: "can be reduced blah blah",
minQuantity: "N/A on orders > 1000"
]
}
This way - you can access price/minQuantity the same way you always would, and Comments are stored in a simple string/string dictionary.
You could also cache those comments in a totally different call ... So you pull them separately from the actual object definition.
Data Storage
Again, depending on your db, you could store comments as json in a text field, or you could store them normalized in a table that has ObjectType,EntityId,FieldName,Comment in it. Up to you, but I'm guessing you don't need them in "every" table -- just occasionally want to add label/comments to fields.
Let me know the middle tier (eg - c#) and maybe we can turn that json into an actual class in your middle tier.
public interface IProduct {
string ProductId {get; set; }
string ProductName {get; set; }
Double Price {get; set; }
int minQuantity {get; set; }
Dictionary<string,string> Comments {get; set; }
}
As a simple example.
Finally, in Angular/Controller
For the front end, you could create a simple property that returns the correct comment:
HTML:
<input ng-model="Price" /><p>{{getComments("Price")}}</p>
Controller:
$scope.getComments = function(fieldNm) {
if($scope.product==undefined
|| $scope.product.Comments.length==0) {
|| $scope.product.Comments.hasOwnProperty(fieldNm)==false) {
return '';
}
return $scope.product.Comments[fieldNm];
}
Or, you could create a directive to accomplish the same thing universally (so you don't have to repeat code in several controllers.
You could try a class structure like this
public class Field
{
private string Value;
private string Comment;
}
public class ViewModel
{
private Field Price { get; set; }
private Field SomeOtherFiled { get; set; }
}
One downside will be to access the value you'll have to do Price.Value or for comment Price.Comment (but it makes sense logically anyway)
The best solution I found is to create a Dictionary<string, string> in the model to store notes, with keys set using nameof(MyAttribute). Notes will have to be retrieved with TryGetValue(), but it is less awkward than constantly typecasting or duplicating fields, and it is easily accessible from views.
Model:
public virtual IDictionary<string, string> Notes { get; set; }
View:
#Html.EditorFor(model => model.Notes[nameof(model.MyAttribute)], new { htmlAttributes = new { #class = "form-control" } })
If I need to manipulate the note:
string myNote;
if (MyModel.Notes.TryGetValue(nameof(MyModel.MyAttribute), out myNote))
{
// Do something with the note
}
else
{
// There is no note for the given attribute
}

Entity Framework query SPA [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I am new to both SPA and Entity Framework and I have a question about the right/preferred way to do this.
I've got a web page to search customers by some filters (like name, surname, birthday date, phone number).
With ajax I pass from View to Controller a ViewModel object like this:
public class CustomerSearch
{
public string Name { get; set; }
public string Surname { get; set; }
public DateTime? Birthday{ get; set; }
public string Phone{ get; set; }
}
Into controller I've got this search method:
public List<CustomerList> GetCustomersList(CustomerSearch cs)
{ ..... }
In my application there are also DataAccess objects.
Now, the question is: how I can to do the query to database in smart mode?
I've thinked some scenario but i don't know which is the best about the layer separation.
I can ask to model an IQueryable object and perform the Where condition into controller
I can create a DataAccess method with the filters like parameters
I can create a Customer object (model object) filled with the filters value and pass this to model that perform the query
Which is the best method?
Thanks in advance.
Daniele
I would suggest the first option you present for the following reasons:
Your second option would possibly require a lot of parameters if the number of possible search queries grows. It is generally not recommended to have a very large number of parameters since it leads to readability issues. (e.g. calling a method with 30 parameters)
Your third option would make it impossible to create a query like 'BirthDate in 1998' or 'Surname starts with Q'.
By creating a class specifically for the purposes of querying you can do something like the following:
public class CustomerQuery
{
public string Name { get; set; }
public DateTime? BirthDay { get; set; }
internal IQueryable<Customer> Apply(IQueryable<Customer> query)
{
var result = query;
if (!string.IsNullOrWhiteSpace(Name))
{
result = result.Where(c => c.Name == Name);
}
if (BirthDay.HasValue)
{
result = result.Where(c => c.BirthDay == BirthDay.Value);
}
return result;
}
}
Pay specific attention to the internal visibility of the Apply method. If you define this class in your Data Access Layer and this is defined in a separate C# project, the Apply method will only be visible to this Data Access Layer and not to the GUI project.
Calling it would be:
public List<Customer> GetCustomersList(CustomerQuery customerQuery)
{
using (var context = new MyDbContext())
{
var customers = context.Customers;
return customerQuery.Apply(customers).ToList();
}
}
This can be further extended to support e.g. different types of string search (Contains, StartsWith etc):
public enum TextFilterType
{
StartsWith,
EndsWith,
Contains,
ExactMatch
}
public class StringQuery
{
private readonly string _value;
private readonly TextFilterType _filterType;
public StringQuery(string value, TextFilterType filterType)
{
_value = value;
_filterType = filterType;
}
public string Value
{
get { return _value; }
}
public TextFilterType FilterType
{
get { return _filterType; }
}
}
If we would apply this to the CustomerQuery type:
public class CustomerQuery
{
public StringQuery Name { get; set; }
}
Then you look at the FilterType property of the StringQuery to find out if you need to do Contains, StartsWith etc.

C# Complex Property Setter option

I have an ASP.Net MVC 5 (C#) application and I'm giving my users the ability to like posts and comments.
for this I have a Model called Likes with the following Properties:
public class Like
{
public Like()
{
this.CreatedUTC = System.DateTime.UtcNow;
this.isActive = true;
}
public long id { get; set; }
public string UserID { get; set; }
public bool isActive { get; set; }
public LikeType Type { get; set; }
public DateTime CreatedUTC { get; set; }
}
Type is an enum and it can be either Comments or Posts. I've also added the following Navigation Property to both Post Model and Comment Model:
public virtual ICollection<Like> Likes { get; set; }
My question is, can I have a setter function in the above line of code where it would automatically set Comments and Posts for the Like type? I know I can use the Value variable in the Setter but using Google I couldn't find how to use it for complex types as I have above (Like).
I'm sure this would be a better way of doing this than in the repository manually set that enum every-time I'm going to save a like.
UPDATE:
Seeing how we're starting a nice little conversation about this Questions, I will throw another alternative in the mix.
How about two Tables with a base class of Like, one CommentLikes and the other PostLikes Seeing that the size of this table will grow really fast, I'm thinking separating them would possibly be a good thing, Right?
I'd rather drop the "LikeType" and either have Comment and Post entity in the Like entity and distinguish by one of them being null or introduce two new entities
public class CommentLike
{
public Comment Comment { get; set; }
public Like Like { get; set; }
}
which holds a comment and a like and PostLike which holds a Post and a Like. The Comment then looks like this
public Comment
{
public virtual ICollection<CommentLike> { get; set; }
}
Another alternative is to create separate tables for comment and post likes. While what you ask for is definitely doable I would recommend more verbose but simpler solution which will result in code that is easier to maintain and has less bugs. Is there any specific reason you want to have a LikeType property?
I had same problem but didnt encounter an easy way.
class Post{
public virtual ICollection<Like> Likes {set;get;}
}
class Comment{
public virtual ICollection<Like> Likes {set;get;}
}
Then:
class Like{
//....
}
You dont need a bi-directional relationship. Do you have a case where you need to query Likes table? and if you do, you will have to manage parsing it as ENUM somewhere which can be an extension method.
EF will create Post_Id and Comment_Id implicityly in your table design. You wont be able to query it but you wont need to. IN my experience i never needed to.
My question is, can I have a setter function in the above line of code
where it would automatically set Comments and Posts for the Like type?
I assume you are using T4 template or the classes that were generated by EF are partialthen you can extend it by creating another partial class and a wrapper property for Likes
// Backing field
private ICollection<Like> _likesWrapper;
public ICollection<Like> LikesWrapper {
get {
// Lazy loading
if(_likes == null)
{
// Just create a new list or load it from the database.
_likes = new List<Like>();
}
return _likes;
}
set {
foreach(var val in value)
{
//Set the comment and posts
}
Likes = value;
}

Am I taking value objects too far (DDD) [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
EDIT:
For clarity, this question is related to DDD, which has a concept called Value Objects, these are not Value Types, they are a way of building objects in such a way that the contents make up the identity, I was trying to understand how far these concepts should apply (From Comments it seems they should not seep outside domain). This question may look odd for people not familiar with DDD but to be clear it is about a very specific mechanism for creating objects NOT creating value types.
Consider the following sample code, which has two Value Objects:
public class SqlServerConnectionSettings
{
public string DatabaseName { get; set; }
public string ServerName { get; set; }
public SqlServerCredentials Credentials { get; private set; }
public SqlServerConnectionSettings(SqlServerCredentials credentials)
{
Credentials = credentials;
}
public string AsConnectionString()
{
//Snip
}
}
public class SqlServerCredentials
{
public string Username { get; private set; }
public string Password { get; private set; }
public bool UseIntegratedSecurity { get; private set; }
public SqlServerCredentials(string username = "", string password = "", bool useIntegratedSecurity = true)
{
Username = username;
Password = password;
UseIntegratedSecurity = useIntegratedSecurity;
}
public string AsConnectionStringCredentials()
{
//Snip
}
}
Rather than have distinct params for Username, Password, UseIntegratedSecurity I have created a value object to hold them. My question is, Is this taking the concept too far, have I misunderstood the point value objects have been designed for?
Looks good to me. You group items which belong together into cohesive units, what could be wrong about that?
It depends on your context.
If you define SqlServerCredentials as an Entity, yes, you're going too far :
"An entity is an object that is not defined by its attributes, but rather by a thread of continuity and its identity."
If you define SqlServerCredentials as a Value Object, you're right (don't forget that it should be immutable !):
"A value object is an object that contains attributes but has no conceptual identity. They should be treated as immutable."
If you define SqlServerCredentials as an Aggregate, you're right, too :
A n aggregate is a collection of objects that are bound together by a root entity, otherwise known as an aggregate root. The aggregate root guarantees the consistency of changes being made within the aggregate by forbidding external objects from holding references to its members.
In conclusion, in a DDD way, if you're not considering SqlServerCredentials as an entity, it's ok. But it's all about context.

Categories

Resources