Correct use of properties and auto implemented properties? - c#

I'm only at chapter 5 in "Essential C#" and not sure if i understand the difference correctly. I tried to make the model below to test one instance of everything in the properties chapter - and it works - but is the example acceptable use of the two ways one can implement properties or are there better ways?
using MarkdownSharp; // StackOverflow's md processor
public class Article
{
public string Headline { get; set; }
public string Content
{
get
{
return _content;
}
set
{
var md = new Markdown();
var html = md.Transform(value);
_content = html;
}
}
private string _content;
public DateTime Published { get; set; } = DateTime.Now;
}

This question may be better suited for codereview.stackexchange, although it's perhaps too tiny a snippet and to vague a question for that.
Personally, I shy away from magic properties that act in surprising ways. It tends to make for APIs that can be hard to use because they are surprising, even if they are somehow “clever” under the hood. You have a property where you set a different value than the one you get out. One thing where this can break would be the += operator, which suddenly would work in very weird ways with your Content property.
I'd probably go with something like
public class Article
{
private string content;
private string renderedContent;
public string Headline { get; set; }
public string Content
{
get { return content; }
set
{
content = value;
renderedContent = null; // reset cached rendered content
}
}
public string RenderedContent
{
get
{
if (renderedContent == null)
{
renderedContent = new Markdown().Transform(content);
}
return renderedContent;
}
}
public DateTime Published { get; set; } = DateTime.Now;
}
As for whether to use field-backed properties, or auto-properties, or computed properties ... that's up to you to decide based on what the property is supposed to do. Auto-properties are fine for simply storing and retrieving a value, e.g. Published or Headline here. You need the explicit backing field as soon as you do something more than just reading or writing it in the getter and setter, as shown here in Content. RenderedContent could be just a computed property, but I chose to cache the value after initial conversion because you kinda do the same. This pattern here doesn't convert the Markdown until it's actually needed, though.

Related

How to retrieve property from GameSparks inside Unity

I am going crazy... I am missing something and I can't see what?!?!
I have created a property called "GAME_SETTINGS" inside the gameSparks admin area and have included this in it:
{
"AppVersionIOS": 1,
"AppVersionAndroid": 1
}
I am then trying to retrieve it inside Unity like this:
new GameSparks.Api.Requests.GetPropertyRequest().SetPropertyShortCode("GAME_SETTINGS").Send((response) => {
if (!response.HasErrors) {
Debug.Log("Setting Achieved: "+response.JSONString);
} else {
Debug.Log("Error Getting Settings");
}
});
I can see that I am getting the settings in my Debug.Log:
Setting Achieved: {"#class":".GetPropertyResponse","property":{"AppVersionIOS":1,"AppVersionAndroid":1},"requestId":"XXXXXXXXXXXXXXX","scriptData":null}
My question is though... How do I get the properties AppVersionIOS and AppVersionAndroid inside an Dictionary so I can call on them from other scripts...
Really hoping for help in this matter and thanks in advance :-)
I actually work for GameSparks and noticed your question so set up an account to answer you.
The property values returned in the JSON are of nullable type : https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Best practice is to parse the values before they are cached in a Dictionary or otherwise.
The following code should allow you to get those properties, then you may store them in a dictionary as you see fit.
public void GetProperties()
{
new GameSparks.Api.Requests.GetPropertyRequest()
.SetPropertyShortCode("GAME_SETTINGS")
.Send((response) =>
{
if (!response.HasErrors)
{
print(response.JSONString);
int androidProperty = (int)response.Property.GetInt("AppVersionAndroid");
int IOSProperty = (int)response.Property.GetInt("AppVersionIOS");
print("AndroidProperty:" + androidProperty);
print("IOSProperty:" + IOSProperty);
}
else
{
Debug.LogWarning(response.JSONString);
}
});
}
Hopefully this solves your problem. If you have any other questions please feel free to head to our website and log a ticket with us.
Regards, Patrick.
Notice: This answer assumes that the API doesn't have a way of converting this into a nice object which you can easily manipulate / parse, so it converts it itself using some class. It's however very likely that your API offers such a function somewhere, so you'd be better be looking in the documentation again. I guess it's somewhere near https://api.gamesparks.net/#getpropertyrequest .
You have the JSON document already, all you have to do is parse it. That'd be easier in a JavaScript file than in C#, but you can also use the JsonUtils class there, see http://docs.unity3d.com/Manual/JSONSerialization.html . Let http://json2csharp.com/ convert that JSON to a class layout for you and you get
public class Property
{
public int AppVersionIOS { get; set; }
public int AppVersionAndroid { get; set; }
}
public class RootObject
{
public string __invalid_name__#class { get; set; }
public Property property { get; set; }
public string requestId { get; set; }
public object scriptData { get; set; }
}
Now just take the string and serialize it into an RootObject.
new GameSparks.Api.Requests.GetPropertyRequest().SetPropertyShortCode("GAME_SETTINGS").Send((response) => {
if (!response.HasErrors) {
Debug.Log("Setting Achieved: "+response.JSONString);
//Serialization
var info = JsonUtility.FromJson<RootObject>(response.JSONString);
//Print the AppVersionIOS property
Debug.Log("App Version iOS: " + info.Property.AppVersionIOS);
} else {
Debug.Log("Error Getting Settings");
}
});
You might need some mofication in the data types of your class (e.g. make object scriptData to string scriptData if there can be an actual string in it), but that should be it. Have fun.

Attributes of properties in MetadataType are ignored by EntLib Validation

It's an EntLib-Validator-issue again. I'm playing with EntLib 5.0 in C# and .Net 4.0 on XP pro.
I have some business objects (partial classes) generated by T4 templates. So I decided to put their validation attributes in buddy-classes by using MetadataTypeAttribute as definitely recommended by the documentation of entLib 5.0 (msdn).
But the Validator object I get from the ValidatorFactory doesn't know about the validation attributes, defined in the metadata-class.
The business object is defined like this:
[MetadataType(typeof(PatientMetadata))]
public partial class Patient
{
private string _Name;
private int _DiagnosisCount;
public int DiagnosisCount
{
get
{
return _DiagnosisCount;
}
set
{
if (value != _DiagnosisCount)
{
_DiagnosisCount = value;
}
}
}
public string Name
{
get
{
return _Name;
}
set
{
if (value != _Name)
{
_Name = value;
}
}
}
}
And the metadata class like this, according to documentation:
public class PatientMetadata
{
[RangeValidator(4)]
public int DiagnosisCount { get; set; }
[StringLengthValidator(64, ErrorMessage = "Name must not exceed 64 chars.")]
public string Name { get; set; }
}
If I know try to do validation this way:
var factory = ValidationFactory.DefaultCompositeValidatorFactory;
var validator = factory.CreateValidator<Patient>();
...then watching into validator (during debugging) already says, that it's just an AndCompositeValidator without any children validators.
Again, if I put the validation attributes right in the Patient class, it works perfectly.
By now, I have no real idea, what I'm missing here, since I think doing everything according to the docs.
Thanks in advance to you guys!
The property names of the metadata class must match the property names of the main class.
In your case your metadata class should look like:
public class PatientMetadata
{
[RangeValidator(0, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Ignore)]
public int DiagnosisCount { get; set; }
[StringLengthValidator(6, ErrorMessage = "Name must not exceed 6 chars.")]
public string Name { get; set; }
}
Also, the docs indicate the accepted approach is to declare all return types as object. However, the docs also talk about using properties but in their example use fields so take it under advisement. :)

Design Pattern for creating a set of data objects

I'm writing some code to do some stuff and I'm pretty sure its not well designed at the moment but I can't think how I should be refactoring it to make it nicer...
The simple summary is that I have some code which goes through some files in a directory structure and different directories contain different content types. I have a limited number of these content types and currently I have a content type object that I am just creating a lot of to add to a list in a way such as follows:
contentTypes.Add(new ContentType { ContentName = "2010 Call Report", FolderName = "2010 Reports", RenameFile = false });
contentTypes.Add(new ContentType { ContentName = "2010 Email Report", FolderName = "2010 Reports", RenameFile = false });
contentTypes.Add(new ContentType { ContentName = "Above Average Call Recording", FolderName = "Call Recordings", RenameFile = true, HasMultiple = true });
contentTypes.Add(new ContentType { ContentName = "Below Average Call Recording", FolderName = "Call Recordings", RenameFile = true, HasMultiple = true });
This really doesn't feel right (11 lines of virtually identical code in total) but I can't think what else I should be doing.
The ContentType class contents a few properties that can be seen above and a single public method called GetNewFilename. Currently the GetNewFilename method is very simple and shared by all content types. However, I now want to have a few of the ContentType objects to have their own versions of this method...
Things I have considered are:
1) Subclass ContentType to create a class for each content type
This didn't seem right to me because I'd have 11 classes, all of which never have their information altered and which there is never any point in having more than one of. This didn't same right for a class (I know about singletons but have heard that if you are using them you may well be doign it wrong).
2) Func property on the ContentType
I figured that I could set a delegate on the ContentType to deal with the GetNewFilename function being different but it still then feels messy generating them in the way described above.
3) Factory Classes
I've never had to use Factory classes before (as far as I'm aware) but I know they are used for generating classes. My reading on them suggested that this pattern was used for generating different subtypes rather than just a set of instances of a class.
4) Config file
The data as I have it above could all be put in a config file or database or something and then loaded up and looped through to generate it more nicely (this only just occured to me) but it still wouldn't solve the problem of the varying getNewFilename method. I am not sure I can put a delegate in a config file easily. :)
5) Having all the different getNewFileName methods on one class
I could just have the content class have all the different methods I could want and use some kind of select to then choose the right one. This just seems to be missing the point a bit too though.
So can anybody suggest a good way to do this?
Here is the current signature for my ContentType class (with logic cut away - ask if you think its relevant).
public class ContentType
{
public string ContentName { get; set; }
public string FolderName { get; set; }
public bool RenameFile { get; set; }
public bool HasMultiple { get; set; }
public string GetNewFilename(string originalFilename, int fileIndex)
{...} // This method needs to do diffent things for different contenttypes
}
If you want more details of how this class is used then ask and I can paste it in but I didn't want to swamp the class in code that I didn't think was that relevant.
This is only for a one use bit of code (to move files around to appropriate directories to put on a new website and ensure they are named correctly) so best possible code isn't vital but its going to bug me if I don't at least know what I should be doing. If the correct way looks like it will take too long (eg rewrite code from scratch) then I won't bother but at least I'll know for next time. :)
P.S. I realise now also that a constructor or two to set those initial values and making them readonly would be an appropriate change to make to neaten it up but still doesn't solve all my problems.
Have your ContentType class be a base class and make the GetNewFilename method virtual. Derive from ContentType classes for each file-type that may need special handling in the GetNewFilename method and override the virtual implementation. Then just create instances of those inherited classes as needed when the file-types that require special handling are found in your directory search, otherwise just create an instance of ContentType class.
public class ContentType
{
public virtual string GetNewFilename(string originalFilename, int fileIndex)
{
// get file name here
}
}
public sealed class SpecialContentType : ContentType
{
// Inherrits all the properties of ContentType
public override string GetNewFilename(string originalFilename, int fileIndex)
{
// get special file name here
}
}
Another pattern to consider might be an interface or abstract class. Yes, you'd have 11 classes, but that's not necessarily a bad thing. It would keep your concerns cleanly separated while still offering a common framework.
If GetFileName works the same way in several cases, you could implement an abstract class with a virtual GetFileName method. This would limit the amount of new code you have to write, only overriding when necessary:
public abstract class ContentType
{
public string ContentName { get; set; }
public string FolderName { get; set; }
public bool RenameFile { get; set; }
public bool HasMultiple { get; set; }
public virtual string GetFileName()
{
//Base GetFileName implementation
return "filename";
}
}
For #4 you could use an IoC container like Unity or StructureBuilder. Then provide a class for the 2nd part:
public interface INewFilenameService {
string FileName {get;set;}
}
public class ContentType {
private INewFilenameService newFilenameService;
public ContentType(INewFilenameService service) {
this.newFilenameService = service;
}
public string ContentName { get; set; }
public string FolderName { get; set; }
public bool RenameFile { get; set; }
public bool HasMultiple { get; set; }
public string GetNewFilename() {
return service.Filename;
}
}
then you could instantiate your content type list either in config or at runtime.

c# -> javascript, Json decoding misses property

I have a c# object (below) that I'm trying to send to my javascript.
My problem is, that while I can iterate over the items in the list, I can't get to the string-property ('Period').
Referencing the object in JS shows no property at all. After Json-encoding in c#, I can still see the property just before returning it to caller (hovering over the result variable in below function):
[OutputCache(Duration = 0, VaryByParam = "None")]
public JsonResult GetRankingList() {
Response.ContentType = "text/javascript";
var user = _userService.GetUserByPrincipal(User);
// Note, we do this while the user waits as we need to make progress in repeated calls to get the compared ranking list.
_businessLogicServiceMaintenance.PerformMaintenanceSteps();
//TODO: Replace with userid (Guid)
var rankingList = _presenterService.GetRankingListForDisplay(user);
if (rankingList == null)
return Json("");
var result = Json(rankingList);
return result;
}
How on earth can I get past this? Any comments appreciated!
Yours, Anders, Denmark,
public class RankingListForDisplay : List<RankingListLine>
{
public string Period { get; set; }
}
Thanks for taking your time - I found a solution.
I changed above implementation of RankingListForDisplay to the one below. For some reason json likes it way better ;-)
public class RankingListForDisplay
{
public List<RankingListLine> Lines { get; set; }
public string Period { get; set; }
public RankingListForDisplay()
{
Lines = new List<RankingListLine>();
Period = "<Unspecified>";
}
}

IDataErrorInfo with complex types

I have an Address object defined simply as follows:
public class Address
{
public string StreetNumber { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
Fairly simple. On the advice an answer to another question I asked, I am referring to this blog post when databinding my UI to an object of type Person (which contains an Address MailingAddress field).
The problem is that the IDataError interface method isn't validating any of the properties of the Address type.
public string this[string columnName]
{
get
{
string result = null;
// the following works fine
if(columnName == "FirstName")
{
if (string.IsNullOrEmpty(this.FirstName))
result = "First name cannot be blank.";
}
// the following does not run
// mostly because I don't know what the columnName should be
else if (columnName == "NotSureWhatToPutHere")
{
if (!Util.IsValidPostalCode(this.MailingAddress.PostalCode))
result = "Postal code is not in a know format.";
}
return result;
}
}
So, obviously I don't know what the columnName will be... I've stepped through it and it has never been anything other than any of the public properties (of intrinsic types). I've even tried running and breaking on a statement like:
if (columnName.Contains("Mailing") || columnName.Contains("Postal"))
System.Windows.Forms.MessageBox.Show(columnName);
All to no avail.
Is there something I'm missing?
You need to define IErrorInfo on all the classes that you want to supply error messages for.
Take a look at my answer here.
This explains how to use a modelbinder to add 'class-level' checking of your model without having to use IDataError - which as you have seen here can be quite clumsy. It still lets you use [Required] attributes or any other custom validation attributes you have, but lets you add or remove individual model errors. For more on how to use data annotations I highly recommend this post from Scott Gu.

Categories

Resources