Auto Encapsulate Field Refactoring, Difference between 'Use field' and 'Use Property'? - c#

On Visual Studio 2017, I have two options when using the Auto Encapsulate Field Refactoring Tool:
Use Property
Still use field
I have tested the different option on a basic class:
public class Test_EncapsulateFieldRefactoring_Property
{
public int id;
public string name;
}
But both option gave the same result:
public class Test_EncapsulateFieldRefactoring_Property
{
private int id;
private string name;
public int Id { get => id; set => id = value; }
public string Name { get => name; set => name = value; }
}
Why do those options exist? Where is the difference (in code generated , "useage"*)?
Disclamer:
The screenshot is a on French VS. So option translations are made by me, real option text may differ.
I know the difference between field and property. I have checked a lot of topics to see if it was not a dupe. I could have missed one.
*, Can't find a good translation for this one: "in the way you use it". But in this context not the difference in use between as field and property but in the menu option.

In English, the options are called:
Encapsulate field (and use property)
Encapsulate field (but still use field)
The difference is in what it does to usages of the field. The first option will update all usages of that field to use the new properties that it creates. The second option doesn't change existing usages of the field elsewhere in your code.
So if elsewhere you have this code:
var test = new Test_EncapsulateFieldRefactoring_Property();
test.name = "Hello";
You'll find that the first option updates test.name to the new test.Name property, but the second option doesn't.

Related

Assigning Dynamic Variables from an Input Model C#

I am having some issues understanding how I can assign dynamic values from another class into other variables - I have tried using the correct namespaces, correct syntax and reading up on the documentation that the error provides - however no luck even when trying to implement examples shown. I have very little knowledge in regards to C# as I am mainly doing front end, however have to step up and start picking up some Back end oriented things at the company I work at
The current code I have is as follows:
BrazeConnectionInputs.cs
namespace Workflow.Connector.Braze.Models
{
public class BrazeConnectionInputs
{
public string Username { get; set; }
public string Password { get; set; }
}
}
CreateCampaign.cs
public class CreateCampaignRunner
{
private const string Username = BrazeConnectionInputs.Username; // BrazeConnectionInputs.Username errors
private const string Password = BrazeConnectionInputs.Password; // BrazeConnectionInputs.Username errors
}
You need to learn about objects vs classes. You should have an instance of the source class (BrazeConnectionInputs) that might be called something like model.
You can then explicitly assign across by creating a new instance of CreateCampaignRunner like var runner = new CreateCampaignRunner() and then assign the values in a number of ways:
Explicitly like runner.UserName = model.UserName
By using an explicit constructor var runner = new CreateCampaignRunner(model)
Object initializer syntax
Other ways are available
Highly recommend you do a basic C# course

DotLiquid, some beginner questions/observations

I'm investigating using dotliquid to replace a home grown piece of templating code and I'm wondering about the best way to achieve my goal.
The old code used to use sigils in the template and, together with a Dictionary, used regexes to search and replace. So you did something like this in the template file:
Specific error: {#ErrorId#}
Error description: {#Description#}
Additional information:{#AdditionalInformation#}
And in the C# code:
Dictionary<string, string> tokensAndValues = new Dictionary<string, string>
{
{#"ErrorId", errorId},
{#"Description", description},
{#"AdditionalInformation", additionalInformation}
};
I came across dotnetliquid and it appears quite powerful (possibly overkill for my needs?). I've got it working but I want to ask if I'm going about this in the correct fashion?
It appears I'm forced to declare a class viz.
public class EmailTemplateInfo : Drop
{
public string ErrorId { get; set; }
public string Description { get; set; }
public string AdditionalInformation { get; set; }
}
And then use that as follows:
Template.NamingConvention = new CSharpNamingConvention();
Template template = Template.Parse(templateText);
EmailTemplateInfo emailTemplateInfo = new EmailTemplateInfo
{
AdditionalInformation = additionalInformation,
Description = description,
ErrorId = errorId
};
string htmlText = template.Render(Hash.FromAnonymousObject(new {emailTemplateInfo = emailTemplateInfo }));
A few questions:
Is this the correct way to do this? If it is then I'll propose doing an addition to the docs that demonstrates this functionality.
Secondly in the template that I use do I need to qualify the placeholders with the name of the variable like this?
Specific error: {{emailTemplateInfo.ErrorId}}
Error description: {{emailTemplateInfo.Description}}
Additional information:{{emailTemplateInfo.AdditionalInformation}}
I can't see how the naming convention declaration [Template.NamingConvention = new CSharpNamingConvention();] ties in with the template variable declaration below it. Is there some sort of global caching going on?
Yes, inheriting from Drop is one way to do it. The other mechanism that DotLiquid provides is Template.RegisterSimpleType(...) - see the unit tests for examples.
Yes, you do need to qualify property names with the name of the variable, as in your example. The alternative would be to create a Hash containing top-level keys for AdditionalInformation, Description, ErrorId, and pass that to template.Render(...). You can do that using Hash.FromDictionary(...), as shown here.
The naming convention doesn't have a connection to the variable declaration. The naming convention is only used when resolving property names. For example, if you used RubyNamingConvention, then you'd need to write {{ emailTemplateInfo.additional_information }} in your template.

How do I change an auto-implemented property to use a private member variable while keeping the table/column association unchanged?

I want to change a C# class member from being an auto-implemented property (auto-property?) to use a private member variable instead, in my Windows Phone C#-based app. The change is simple except that the class represents a database table. A simplified version of the original class looks like this:
[Table]
public class ResourceItem
{
[Column(IsPrimaryKey=true, IsDbGenerated=true)]
public long m_ItemId { get; set; }
[Column(CanBeNull=true)]
private int? m_Order;
}
A bad decision years ago has led to me now need a custom getter method for m_Order. The new class looks like this:
[Table]
public class ResourceItem
{
[Column(IsPrimaryKey=true, IsDbGenerated=true)]
public long m_ItemId { get; set; }
private int? _order;
[Column(CanBeNull=true)]
public int? m_Order
{
set { _order = value; }
get { return _order == 999999 ? 0 : _order; }
}
}
This all works fine and when the unwanted 999999 value is discovered, the code returns 0, which is totally appropriate.
The original bug is not the issue, nor is the change to the class in regards to C#. The problem is with this being a database column. When I run the new app with a database created by the old version of the app, I get "Row not found or changed" errors when an object of this type is updated in the database.
Why does the update cause a problem? Shouldn't the database schema remain completely unchanged by this class change?
Using [Column(CanBeNull=true, UpdateCheck=UpdateCheck.Never)] as the column definition gets rid of the error but I would like to know why the error shows up in the first place.
Is there a different way to specify the Column attribute to avoid the error? Should I use the Column attribute on the private member instead?
And most importantly, are my database updates working correctly now that I've taken away the update check on this column?

Class design best way to handle multi-value options and the selected value?

What's the best way to design a class (or classes) that can hold the potential values of item, as well as the one the user actually selected? I've come across this problem before and always feel like I'm missing a core class design feature.
Right now I usually do something like the following
class MultiChoice
Name (I.e. Box Size)
Default Value ("22x15")
PotentialValues ({"10x10","20x20","22x15"})
But that doesn't handle the actual value the user selected, so I add that in.
class MultiChoice
Name (I.e. Box Size)
Default Value ("22x15")
PotentialValues ({"10x10","20x20","22x15"})
SelectedValue
That doesn't feel right though, because when I construct a drop-down I'm filling in stuff with SelectedValue = null. Then when I store the data, I'm storing all the options too, which I don't need.
Is there a better way to handle this with an interface or other language construct? I always feel like I'm missing something blatantly obvious here.
You really have two separate entities here:
MultiChoiceQuestion
MultiChoiceAnswer
Create two separate classes to represent these two separate concepts.
ASP.NET MVC has the SelectList class. While you might not actually be working in ASP.NET MVC, it seems clear that Microsoft felt that the concept of "backing class for a dropdown" was universal enough to warrant its own class.
In whatever you consider the "Model" (that part of your program containing the business domain classes and business logic), there will always exist database tables that serve as lookups for these dropdowns.
tblCountries
CountryID PK
CountryCode string
FullName string
In your ViewModel, there will be a corresponding list of countries from which you can populate the dropdown:
public class InvoiceViewModel
{
...
public int CountryID { get; set; }
public SelectList Countries { get; set; }
// or
public List<Country> Countries { get; set; }
...
}
Of course, by the time you get to the UI, the actual dropdown contains enough plumbing to hold both the select list and the selected value.
You really only need a single Value field. Set it to whatever you want in the constructor (so it's defaulted when the object is created). You can also change your 'potential values' to be static, so it's the same for the entire class.
public class Box
{
public string Value { get; set; }
public static List<string> AllowedValues { get; private set; }
public Box()
{
AllowedValues.AddRange(new string[]{"10x10","20x20","22x15"});
Value = AllowedValues.First();
}
}
Then when a user changes the value, simply update it.
Box thisBox = new Box();
string val = "22x15";
if (Box.AllowedValues.Contains(val))
thisBox.Value = val;

Obfuscation with JSON.net

I am using Json.Net for serialization and unserialization on a class. When I try to obsfucate the class in an assembly, I will not be able to unserialize the JSON string correctly. I have try using JsonProperty Attribute but it still not able to unserialize correctly.
Does anyone know how to get around this other than setting the class not to obsfucate?
Thanks in advance.
Updates:
I have created a simple class for JSON object as below:
public class JsonTestClass
{
[JsonProperty("JsonID")]
public int Id { get; set; }
[JsonProperty("JsonName")]
public string Name { get; set; }
[JsonProperty("JsonYesNo")]
public bool YesNo { get; set; }
}
And the code to serialize JsonTestClass objects into Json string is:
//Serialize
var jsonObj = new JsonTestClass()
{
Id = 1,
Name = "John",
YesNo = true,
};
var JsonStr = JsonConvert.SerializeObject(jsonObj);
Trace.WriteLine(">>" + JsonStr);
And unserialize Json string to JsonTestClass is as follow:
//Unserialize
var JsonStr = "{\"JsonID\":1,\"JsonName\":\"John Abc\",\"JsonYesNo\":true}";
Trace.WriteLine("<<" + JsonStr);
var jsonObj = JsonConvert.DeserializeObject<JsonTestClass>(JsonStr);
if (jsonObj == null)
{
Trace.WriteLine("-- JsonObj is null");
}
else
{
Trace.WriteLine(string.Format("-- Id={0} Name={1} YesNo={2}", jsonObj.Id, jsonObj.Name, jsonObj.YesNo));
}
Everything works fine unobsfucated and the debug output for serialization is:
[64200] >>{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
And debug output for deserialization is:
[64200] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
[64200] -- Id=1 Name=John Abc YesNo=True
After the assembly has been obsfucated (using SmartAssembly to obsfucate this) and using dotPeek to see the obsfucated assembly, the only one which somewhat resemble the JsonTestClass are:
namespace
{
internal class
{
}
}
The debug output for serialization is:
[65956] >>{}
The debug output for deserialization is:
[65956] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
[65956] -- Id=0 Name= YesNo=False
Hope this helps to clear things up.
If you are using Dotfuscator which is shipped as Community Edition with Visual Studio 15 and Visual Studio 17, you have to exclude the property names of the object you serialize from renaming. You do this in the Dotfuscator renaming tab.
After that you can serialize and deserialize like normal.
You find a detailed description here in the support corner of the Preemtive Solutions web site.
There are a couple of options, depending on your preference as to maintainability, security, etc.
Excluding properties from obfuscation
If it's just the type names that you're concerned about being obfuscated and not the property names, then you can decorate each property that is to be serialized with the Obfuscation attribute. (Here is the link for Dotfuscator's support for this attribute.) Basically, by excluding the property from renaming, this will allow Json.NET to easily identify the properties to set.
[Obfuscation(Exclude=true, Feature="renaming")]
public int MyProperty { get; set; }
Pros: Easy and straightforward
Cons: You lose some security by not
obfuscating your property names.
Expose the private backing field for deserialization
Another way to get Json.NET to deserialize an obfuscated class is to change the target of the deserialization from the public property to the private field using the JsonProperty attribute, e.g.
[JsonProperty("a")]
private int _myField;
[JsonIgnore]
public int MyProperty
{
get => _myField;
set => _myField = value;
}
NOTE: If you use "MyProperty" or nameof(MyProperty) in the JsonProperty attribute, then depending on your obfuscation settings it's very possible that it will be compiled into the .dll as "MyProperty", thus reducing the overall security that you were trying to achieve with obfuscation in the first place.
NOTE 2: This solution will most likely not work when working with the MVVM design pattern. When using this pattern, a common coding practice is to utilize the property setter to raise the INotifyPropertyChanged event. However, using the JsonProperty and JsonIgnore attributes will cause Json.NET to set the value directly on the private field using reflection instead of the via the property setter. Therefore the change event will not be raised, making this a poor solution in this particular scenario.
Pros: You can maintain full obfuscation of your property names.
Cons: You need to create backing fields for every obfuscated property that you want to participate in serialization/deserialization. Also, may break the INotifyPropertyChanged functionality when using with the MVVM pattern, depending on your implementation details.

Categories

Resources