I was looking for a way to switch my assignments i.e:
a = b;
becomes
b = a;
In case anyone is wondering, it's for loading settings and unloading them.
I crafted a regular expression for it:
Find what: {[^:b]*} = {[^;]*}
Replace with: \2 = \1
This works fine, but is there another way to load and save settings that I'm missing?
An alternative approach: what about making a settings class with a method that copies values? In that way you write the list of assignments only once:
using System;
class Settings {
public int ValueA { get; set; }
public string ValueB { get; set; }
public void CopySettings(Settings other) {
ValueA = other.ValueA;
ValueB = other.ValueB;
}
}
class Program {
static void Main(string[] args) {
Settings a = new Settings() { ValueA = 3, ValueB = "something" };
Settings b = new Settings();
// and then you can do one the following, which will copy all settings
// in both cases...
b.CopySettings(a);
a.CopySettings(b);
}
}
Related
Is there any way I can get the complete path of the property from the property itself ?
I have code design below as something:
class A
{
B BProperty { get; set; }
D DProperty { get; set; }
}
class B
{
D DProperty { get; set; }
}
class D
{
int Value { get; set; }
}
class Verification
{
public static void VerifyAProperty(A source, A dest)
{
VerifyBProperty(source.BProperty, dest.BProperty);
VerifyDProperty(source.DProperty, dest.DProperty);
}
public static void VerifyBProperty(B source, B dest)
{
VerifyDProperty(source.DProperty, dest.DProperty);
}
public static void VerifyDProperty(D source, D dest)
{
//// Here I want to verify source.value with dest.value and if they do not match I want to show an error message.
//// I have requirement to show the complete path of property that is under verification.
//// i.e either A->D->value or A->B->D->value
}
}
This is just a small part of my problem. I have number of similar verification to be done on number of different properties that can be at multiple places in the hierarchy.
I need to verify the source property with the destination property and in case if both do not match, show an error message that provides the path of the property that did not match.
I have tried something by passing a string property to VerifyProperty() function that will be appended as we go down the hierarchy. I just want to know if there is any better way to achieve this.
You can build an example where a property have multiple path:
var d = new D();
var b = new B { DProperty = d };
var a = new A { BProperty = b, DProperty = d };
In this example, the reference is the same in d, a.DProperty and a.BProperty.DProperty. It is the same reference stored at multiple places, hence it can't have an unique path.
That why there is no concept of (unique) property path in C#.
You have to add the path information by your own:
class Verification
{
public static void VerifyAProperty(A source, A dest, string path = null)
{
path += "->A";
VerifyBProperty(source.BProperty, dest.BProperty, path);
VerifyDProperty(source.DProperty, dest.DProperty, path);
}
public static void VerifyBProperty(B source, B dest, string path = null)
{
path += "->B";
VerifyDProperty(source.DProperty, dest.DProperty, path);
}
public static void VerifyDProperty(D source, D dest)
{
path += "->D";
if (source.Value != dest.Value)
Console.WriteLine($"Different values at: {path}");
}
}
An other option is reflection.
The test should check when a train is assigned to a line he losts its previous line. The class Train should implement this test in the function public void AssignTo(ILine l) by following those steps (they need to be respected):
Current assignment = l1
l1.Trains contains THIS
need to remove THIS from l1.trains
need to change current line and add train to new line
internal class Train : ITrain
{
internal Train(string name, Company company)
{
this.Name = name;
this.Company = company;
}
public string Name
{
get;
}
public ICompany Company
{
get;
}
public ILine Assignment
{
get;
private set;
}
public void AssignTo(ILine l)
{
//Current assignment = l1
var l1 = Assignment;
//l1,Trains contains THIS
this.AssignTo(l1.train)
//need to remove THIS from l1.trains
((List<Train>)l1.Trains).Remove(this);
//need to change current line and add train to new line
((List<Train>)l.Trains).Add(this);
Assignment = l;
}
}
}
[Test]
public void T2_when_a_train_is_assigned_to_a_line_he_losts_its_previous_line()
{
ICity s = CityFactory.CreateCity("Paris");
ICompany c = s.AddCompany("SNCF");
ILine l1 = s.AddLine("RER A");
ILine l2 = s.AddLine("RER B");
ITrain t1 = c.AddTrain("RER1");
t1.AssignTo(l1);
t1.Assignment.Should().BeSameAs(l1);
t1.AssignTo(l2);
t1.Assignment.Should().BeSameAs(l2);
l1.Trains.Count().Should().Be(0);
l2.Trains.Single().Should().BeSameAs(t1);
}
The problem with your current interfaces are that ILine.Trains is an IEnumerable, and you can't really remove something from an IEnumerable. In your code, you have assumed that it will always be a List, which you shouldn't really do, but if you can't change the type of ILine.Trains then I guess that's the only way.
Anyway, the reason why your code doesn't work is that you are recursively calling AssignTo for some reason. You should remove this call:
public void AssignTo(ILine l)
{
var l1 = Assignment;
// remove this line
// this.AssignTo(l1.train)
((List<Train>)l1.Trains).Remove(this);
((List<Train>)l.Trains).Add(this);
Assignment = l;
}
Although this isn't required, (it seems to be one of your requirements), you need to check whether l1.Trains contains this first:
var l1 = Assignment;
if (l1.Trains.Contains(this)) {
((List<Train>)l1.Trains).Remove(this);
}
((List<Train>)l.Trains).Add(this);
Assignment = l;
A quick question on OOP. I am using a list together with a class and class constructor. So I use the class constructor to define the data set and then add each record to my list as the user creates them.
My questions is once the data is in the list and say I want to alter something is it good practice to find the record, create an instance using that record and then use my class methods to do whatever needs doing - and then put it back in the list?
For example below I have my class with constructor. Lets say I only want the system to release strCode if the Privacy field is set to public. Now just using Instances I would use for example Console.WriteLine(whateverproduct.ProductCode) but if the record is already in a list do i take it out of the list - create an instance and then use this method?
class Product
{
private String strCode;
private Double dblCost;
private Double dblNet;
private String strPrivacy;
public Product(String _strCode, Double _dblCost, Double _dblNet, String _strPrivacy)
{
strCode = _strCode;
dblCost = _dblCost;
dblNet = _dblNet;
strPrivacy = _strPrivacy;
}
public string ProductCode
{
get
{
if (strPrivacy == "Public")
{
return strCode;
}
else
{
return "Product Private Can't release code";
}
}
}
Lets say we have the following:
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Amount { get; set; }
private string _test = "Some constant value at this point";
public string GetTest()
{
return _test;
}
public void SetTest()
{
//Nothing happens, you aren't allow to alter it.
//_test = "some constant 2";
}
}
public class Program
{
public static void Main(string[] args)
{
List<Test> listOfTest = new List<Test>()
{
new Test() {Id = 0, Name = "NumberOne", Amount = 1.0M},
new Test() {Id = 1, Name = "NumberTwo", Amount = 2.0M}
};
Test target = listOfTest.First(x => x.Id == 0);
Console.WriteLine(target.Name);
target.Name = "NumberOneUpdated";
Console.WriteLine(listOfTest.First(x => x.Id == 0).Name);
Console.WriteLine(listOfTest.First(x => x.Id == 0).GetTest());//This will alsways be "Some constant value at this point";
Console.ReadLine();
}
}
Technically you could do away with the SetTest method entirely. However, I included it to demonstrate, what it would look like, if you wanted to alter _test.
You don't want to ever create a new instance of a class, you already have an instance of. you can just alter the class where it is allowed by the author of the class, where you need to. And keep that class reference for as long as you need it. Once you are done, the reference will be garbage collected, once the program finds no active reference to your object(instance).
I'm working on some C# code where I have several files that use the same public variables (let's call these variables a, b, and c for now). Disclaimer: please don't berate me on the quality of the code, I didn't write it, it's simply my job to fix it. These variables are public and shared across all files, and should really be an array (a, b, and c all do the same thing, with slightly different properties). I am modifying the largest file of the bunch to take out all references to the variables and replace them with an array letters[], but other files contain disparate references to these variables. Is there any way to, in other files, define a variable or macro of some kind so that I don't have to change every reference in every file?
For example: In the biggest file "main.cs", I used to have:
public string a;
public string b;
public string c;
a = "a";
b = "b";
c = "c";
but I fixed it to have:
string[] letters;
letters[0] = "a";
//etc
Now, in file "small.cs", I have
a = "hello world";
b = "goodbye world";
Instead of having to go through every single file, is there any way that I could just have 'a' be defined as the first element of letters (letters[0]), b reference letters[1], etc? This way, the program would still run, and in the small files, C# would know that any reference to 'a' really means a references to letters[0].
Use a property:
public string A { get { return letters[0]; } }
Reference them from a property:
public string a
{
get
{
return letters[0];
}
set
{
letters[0] = value;
}
}
instead of writing
public string a;
public string b;
public string c;
a = "a";
b = "b";
c = "c";
write
private List<string> vals = new List<string>{ "a", "b", "c" };
public string a { get { return vals[0]; } set { vals[0] = value; } }
public string b { get { return vals[1]; } set { vals[1 = value; } }
public string c { get { return vals[2]; } set { vals[2] = value; } }
I have a linq table "KUND" who is read only to me. It has some special characters in it to which i have writter a function to switch them out to the ones i want.
public static string changeSpecialCharacters(string kund)
{
StringBuilder b = new StringBuilder(kund);
b = b.Replace("Õ", "å");
b = b.Replace("┼", "Å");
b = b.Replace("õ", "ä");
b = b.Replace("─", "Ä");
b = b.Replace("÷", "ö");
b = b.Replace("Í", "Ö");
b = b.Replace("'", " ");
b = b.Replace("¦", "´");
b = b.Replace("Ï", "Ø");
return b.ToString();
}
I now have two questions:
1 Can i add this function to the GET in the autogenerated datacontext so i dont have to call it all over my code? Ive added it but it seems to be deleted whenever i change how my datacontext is (add/remove table). 2 Any suggestions how to make that function better in regards to speed perhaps?
Never edit the .designer.cs; instead, add a second file, and use partial class to add the method, for example:
namespace Your.Namespace
{
partial class YourDataContext
{
// your methods here
}
}
No; you can't add this to the get. Another alternative, though, is an extension method:
namespace Some.Utility.Namespace
{
public static class SomeUtilityClass
{
public static string ChangeSpecialCharacters(this string kund)
{ ... } // note the "this" in the above line
}
}
Now you can use:
string name = obj.Name.ChangeSpecialCharacters();
personally I would rename this to clarify the direction of the change, and have two methods - one to encode, one to decode.
Re doing this for a set of data; perhaps:
public static IEnumerable<SomeType> ChangeSpecialCharacters(
this IEnumerable<SomeType> items)
{
foreach(var item in items)
{
item.Name = item.Name.ChangeSpecialCharacters();
item.Foo = item.Foo.ChangeSpecialCharacters();
...
item.Bar = item.Bar.ChangeSpecialCharacters();
yield return item;
}
}
probably you could initialize your variable as:
private string kund;
public string Kund
{
get
{
return changeSpecialCharacters(string kund);
}
set
{
kund = value;
}
}