I have a C# winform app which is doing a lot of calculation. there is a "run" button to trigger the process. I would like to be able to "re-trigger or re-run or re-submit" the information without having to restart the program. Problem is I have a lot of variables that need to be reset. Is there a way to undef (reset) all parameters?
private Double jtime, jendtime, jebegintime, javerage, .... on and on
Create an instance of an object that stores these variables. Reference this object, and when wanting to "reset", reinstantiate your object. e.g.
public class SomeClass
{
public double jTime;
...
}
...
SomeClass sc = new SomeClass();
sc.jTime = 1;
sc = new SomeClass();
The best way would have been if you had them all in a class.
Then on reset you'd just create a new class with initialized values.
You could use Reflection; although Reflection is the less performant than the other proposed solutions, but I am not entirely sure of your solution domain and Reflection might be a good option.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Data data = new Data();
//Gets all fields
FieldInfo[] fields = typeof(Data).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (var field in fields)
{
//Might want to put some logic here to determin a type of the field eg: (int, double)
//etc and based on that set a value
//Resets the value of the field;
field.SetValue(data, 0);
}
Console.ReadLine();
}
public class Data
{
private Double jtime, jendtime, jebegintime, javerage = 10;
}
}
}
Yes, simply use Extract Method refactoring technique. Basically extract reset logic in a separate method and then just call it when need
private void ResetContext()
{
jtime = jendtime = jebegintime = javerage = 0;
}
Related
using System;
public class Program
{
public static void Main()
{
CloudCollectionHelper cloudHelper = new CloudCollectionHelper();
SlackHelper slackHelper = new SlackHelper();
cloudHelper.DatabaseID=12345;
Console.WriteLine(slackHelper.GetSlackPageTokens());
}
class CloudCollectionHelper
{
public long DatabaseID { get; set; }
}
class SlackHelper:CloudCollectionHelper
{
public long GetSlackPageTokens()
{
return DatabaseID;
}
}
}
current output: 0
Expected Output: 12345
I need output 12345 because DatabaseID from the cloudhelper so i need that databaseID in the slackhelper.
this is my c# online compiler: https://dotnetfiddle.net/QNQeEX
The child class does not get the assigned values from the base class. Becouse there can be mutliple instances from it. For example, if you have
...
CloudCollectionHelper cloudHelper1 = new CloudCollectionHelper();
CloudCollectionHelper cloudHelper2 = new CloudCollectionHelper();
cloudHelper1.DatabaseID = 1234;
cloudHelper2.DatabaseID = 6789;
Console.WriteLine(slackHelper.GetSlackPageTokens()); //It would not know, what value to use.
...
The best way would be assigning the value directly to the child class or using the static modifier.
Edit:
Best way if you need to take this value from the child class for whatever reason would be doing something like this:
...
CloudCollectionHelper cloudHelper = new CloudCollectionHelper();
cloudHelper.DatabaseID = 12345; //First assign the needed Value
SlackHelper slackHelper = new SlackHelper(cloudHelper); //then create a new instance from the child class
...
and add the constructor from the SlackHelper child class like this:
class SlackHelper:CloudCollectionHelper
{
public SlackHelper(CloudCollectionHelper cloudHelper)
{
this.DatabaseID = cloudHelper.DatabaseID;
}
... //Do everything else what this class needs here
}
If the Value from cloudHelper.DatabaseID can update during the runtime, you will need a event to update the child class. It still isn't the best way to do this, because the DatabaseID value is already public and can be accessed without the child class.
Edit 2:
Like I already told you in the comments, you could also avoid this problem with the static modifier. But this will effect every instance made from the CloudCollectionHelper class. As soons as you make it static, this will only hold 1 possible value for all instances.
(Please keep in your mind to use a comment if needed or best case, just avoid Magic numbers)
The property of your Object slackhelper has not been affected.
You don't need to create a CloudCollectionHelper Object.
SlackHelper slackHelper = new SlackHelper();
slackHelper.DatabaseID=12345;
Console.WriteLine(slackHelper.GetSlackPageTokens());
You should create this property inside the class to allow to read the Database ID
public long GetSlackPageTokens()
{
return base.DatabaseID;
}
I need to change a specific property dynamically and have been using this snipplet:
var _oldMethod = typeof(TypeName).GetProperty("OldProperty", BindingFlags.Public | BindingFlags.Static).GetMethod;
var _newMethod = typeof(OwnTypeName).GetProperty("NewProperty", BindingFlags.Public | BindingFlags.Static).GetMethod;
ReplaceMethod(_oldMethod, _newMethod);
...
private static unsafe void ReplaceMethod(MethodInfo _oldMethod, MethodInfo _newMethod)
{
var _oldMethodAddress = new IntPtr((int*)_oldMethod.MethodHandle.Value.ToPointer() + 2);
var _destination = (uint*)_oldMethodAddress.ToPointer();
*destination = (uint)_newMethod.MethodHandle.GetFunctionPointer().ToInt32();
}
Unfortunately this required some decompiling with recreating the original property. What I am looking for now is a a possibility to duplicate and kind of backup the original method and dynamically replace the old method with the new one or restore the original one.
Has anyone an idea how to implement this?
Edit:
I may should have clarified my situation further:
public static class ClassName
{
public static bool Property
{
get
{
// Conditions
}
}
}
I can't access ClassName and need to force Property to false in specific situations and need to replace it to the original return value in other situations. I have been using the ReplaceMethod above mentioned but don't want to decompile and rebuild Property from scratch (instead some kind of backup of the original Property)
First of all, you are handling properties instead of methods.
One easy approach to do this is to replace your properties type by Func<> and this will keep what you're wanting to do easier.
private static void Main(string[] args)
{
var a = new A();
a.Property = Method1;
Console.WriteLine(a.Property.Invoke());
a.Property = Method2;
Console.WriteLine(a.Property.Invoke());
Func<string> oldMethod = a.Property;
Console.WriteLine(oldMethod.Invoke());
Console.ReadLine();
}
public class A
{
public Func<string> Property { get; set; }
}
private static string Method1()
{
return "Method1";
}
private static string Method2()
{
return "Method2";
}
You can change the method as many times as you want and also keep the old one in one variable.
Well recently i came up with an idea (that i really don't know whether it would exist or even work) of automatic updating class's properties using an modified instance of it. And to make my idea a little bit more clear, i will explain it in the code below.
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here is the same employee data collected from the database a year after...
Employee carl_one_year_later = new Employee();
carl_one_year_later.Age = 21;
carl_one_year_later.Salary = 10000;
//Here comes the idea... I wanna dynamically merge the new collected data to the current main instance of the employee, without missing out the unupdated data ex : his name
employee1 = employee2; //using this seems to overwrite the Name Field with null...
Someone might say you can simply achieve this by doing this:
carl.Age = carl_one_year_later.Age;
carl.Salary = carl_one_year_later.Salary;
However, i want a dynamic way to just do this in 1 line of code and let C# handle the property set for me, also it may come in handy if we have a massive class that we don't want to set it's properties every time it is updated one by one.
NB: I hope i succeed in providing a clear image of my idea, and if you find any problem understanding what exactly do i need, just let me know.
using System;
using System.Reflection;
public class Test
{
public class Employee
{
public String Name{get;set;}
public int Age{get;set;}
public int Salary{get;set;}
}
public static void Main()
{
Employee e1 = new Employee{Name="Old", Age=20, Salary=1000};
Employee e2 = new Employee{Age=30, Salary=5000};
Copy(e2, e1);
Console.WriteLine(e1.Name+" "+ e1.Age+" "+e1.Salary );
}
public static void Copy<T>(T from, T to)
{
Type t = typeof (T);
PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props) {
if (!p.CanRead || !p.CanWrite) continue;
object val = p.GetGetMethod().Invoke(from, null);
object defaultVal = p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;
if (null != defaultVal && !val.Equals(defaultVal)) {
p.GetSetMethod().Invoke(to, new[] {val});
}
}
}
}
You can make a CopyTo extension method, like so:
public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach(var p in typeof(T).GetProperties())
{
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
And call it like:
carl_one_year_later.CopyTo(carl);
Although, to be honest, there's a few more checks that should be made, and you'd be better off using something like AutoMapper instead.
Checkout ICloneable OR MemberwiseClone (unless you need to do a deep copy. Then check out a object mapper like Automapper, ValueInjecter or write your own custom object serialization hydrater)
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.
http://msdn.microsoft.com/en-us/library/system.icloneable.aspx
Alternatives to AutoMapper
public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach (var p in typeof(T).GetProperties())
{
if(p.GetValue(fromObj) == null)
{
continue;
}
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
Same as the above answer but just added "if" in "foreach" to skip the null values
The idea itself seems odd to me..
I, myself, would just rather do :
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here we get Carl from the database
Employee carl = GetFromDatabase("Carl") //Illustration
carl.Age = 21;
carl.Salary = 10000;
Your code is like saying nowadays Carl and next year Carl is a completely different person, and coincidentally having all those same attributes.
Although if it really needs to be done, I do tend to prefer Automapper..
I have a static Command class like this (but with many more commands):
class GuiCommands
{
static GuiCommands()
{
addInterface = new RoutedUICommand(DictTable.getInst().getText("gui.addInterface"), "addInterface", typeof(GuiCommands));
removeInterface = new RoutedUICommand(DictTable.getInst().getText("gui.removeInterface"), "removeInterface", typeof(GuiCommands));
}
public static RoutedUICommand addInterface { get; private set; }
public static RoutedUICommand removeInterface { get; private set; }
}
It should use my dictionary to get the texts in the right language, which doesn't work, because my dictionary isn't initialized when the static constructor is executed.
My first attempt was to create a new command-class which derives from RoutedUICommand, override the Text property and call the dict in the get method. But the Text property isn't virtual and neither is the GetText()-Method it calls.
The only thing i can think of is provide a static initialize method in this class that translates all the dict-keys. But this is not very clean IMHO because i have to name every command once again like this
addInterface.Text = DictTable.getInst().getText(addInterface.Text);
and if i forget to name one, there won't be an error, just no translation.
I don't even like that i have to name the command twice in this class and once again in the XAML commandbindings.
Do you have any ideas how this can be solved more elegantly?
I like RoutedUICommands much, but like this they're useless to me. Why couldn't Microsoft add the little word 'virtual' a little more often?? (or make it default like JAVA does?!)
I found an acceptable way by translating all commands automatically using reflection.
This way i at least don't have to add all the commands to another method.
I call the translate-method right after i initialized my dictionary.
public static void translate()
{
// get all public static props
var properties = typeof(GuiCommands).GetProperties(BindingFlags.Public | BindingFlags.Static);
// get their uicommands
var routedUICommands = properties.Select(prop => prop.GetValue(null, null)).OfType<RoutedUICommand>(); // instance = null for static (non-instance) props
foreach (RoutedUICommand ruic in routedUICommands)
ruic.Text = DictTable.getInst().getText(ruic.Text);
}
I am looking to find a way to take two objects that have identical properties and make a call to copy the property values from one object into the other. The the example below assume I have an instance of A and I want to use the data of that instance to hydrate a new instance or C (to keep things terse I used fields instead of properties in the example below)
public class A : B
{
public string prop1;
public int prop2;
}
public class B
{
public byte propX;
public float propY;
}
public class C
{
public byte propX;
public float propY;
public string prop1;
public int prop2;
}
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
//do some work
//maybe <T> generically refactor?
}
}
The merger class is just a psuedo-example, doing this through generics would be optimal but the first thing I question is whether such a capability already exists. I could imagine using reflection to do this myself but just wanted to toss it out for better ideas first.
Real world context: This is actually an MVVM related issue as I am trying to use disparate classes coming back from EF to populate a ViewModel instance.
Check out tools and libraries like AutoMapper - those would handle cases like this with ease - and much more! No need to re-invent the wheel - just use the tool! :-)
You would basically define a map between classes A and C like this:
Mapper.CreateMap<A, C>();
and then later on, you can have AutoMapper do the mapping, based on that map, from an instance of A into an instance of C, something like this:
C yourC = Mapper.Map<A, C>(instanceOfA);
AutoMapper does a default mapping based on property names (and types), but you can extend and influence it in a great many ways to include mappings from one property to another, even if the names (or types) don't match 100%. It's quite flexible and well established - definitely worth a serious look!
using System;
using System.Linq;
using System.Reflection;
public class Merger
{
public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new()
{
var flags = BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic;
var targetDic = typeof(TTarget).GetFields(flags)
.ToDictionary(f => f.Name);
var ret = new TTarget();
foreach (var f in copyFrom.GetType().GetFields(flags))
{
if (targetDic.ContainsKey(f.Name))
targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom));
else
throw new InvalidOperationException(string.Format(
"The field “{0}” has no corresponding field in the type “{1}”.",
f.Name, typeof(TTarget).FullName));
}
return ret;
}
}
class Program
{
static void Main(string[] args)
{
var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f };
var c = Merger.Merge<C>(a);
Console.WriteLine(c.prop1); // prints one
Console.WriteLine(c.prop2); // prints 2
Console.WriteLine(c.propX); // prints 127
Console.WriteLine(c.propY); // prints 0.47
}
}
This isn't the best solution by far, but based on the object graph you've provided, you could probably accomplish this by XML serializing the first object, and XML deserializing the XML stream into the second object.
Your proposed Merger method could possibly look like this:
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
var xmlContent = MyXMLSerializationMethod(copyFrom);
MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo);
return copyTo;
}
}
Good post about using AutoMapper to solve this problem in the context of MVVM and MVC
http://www.bengtbe.com/blog/post/2009/04/14/Using-AutoMapper-to-map-view-models-in-ASPNET-MVC.aspx