I am working on a project where I need to queue up a number of property changes. Let say I have:
public class foo
{
string bar { get; set; }
int bar1 { get; set }
}
I want to have some code that looks like:
//Store value set actions in a queue
foo.SetValue(bar, "abc");
foo.SetValue(bar1, 123);
//Preview changes
foreach(Item change in foo.ChangeQueue)
{
Console.Write(change.PropertyName.ToString());
Console.Write(change.Value.ToString());
}
//Apply actions
foo.CommitChanges();
What is the best way to accomplish this?
You can use Dictionary<string,object> as ChangeQueue to store your values.
You can iterate as,
foreach(KeyValuePair<string,object> item in ChangeQueue){
Console.WriteLine(item.Key);// name of property
Console.WriteLine(item.Value); // value of property
}
public void SetValue(string name, object value){
PropertyInfo p = this.GetType().GetProperty(name);
// following convert and raise an exception to preserve type safety
ChangeQueue[name] = Convert.ChangeType(value,p.PropertyType);
}
public void ApplyChanges(){
foreach(KeyValuePair<string,object> item in ChangeQueue){
PropertyInfo p = this.GetType().GetProperty(item.Key);
p.SetValue(this, item.Value, null);
}
}
"Type-safe" version which uses callbacks. This will not automatically remove duplicate-settings. It also does not use reflection and so property-name errors will fail on compilation. This method could be expanded to require a "name" and remove duplicates by using a Dictionary backing (as per Akash's answer) or allow the "setter" to return a value (such as success or failure or the old value, or whatnot).
interface Setter {
void Apply();
}
class Setter<T> : Setter {
public T Data;
public Action<T> SetFn;
public void Apply() {
SetFn(Data);
}
}
List<Setter> changeQueue = new List<Setter>();
void SetValue<T>(Action<T> setFn, T data){
changeQueue.Add(new Setter<T> {
Data = data,
SetFn = setFn,
});
}
void ApplyChanges(){
foreach (var s in changeQueue){
s.Apply();
}
}
// .. later on
SetValue(x => System.Console.WriteLine(x), "hello world!");
ApplyChanges();
This method can also be trivially used "outside" the objects being monitored because all the operations are in potential closures.
Happy coding.
Related
I'm tring to create a list of different types object that derivated from the same parent and access its custom properties.
These are my classes:
abstract class Signal
{
}
abstract class Signal<T>:Signal
{
public T Value { get ; set; }
public Signal(T value)
{
Value = value;
}
}
class scalar_signal : Signal<int>
{
public scalar_signal(int value):base(value)
{
}
}
class array_byte_signal: Signal<byte[]>
{
public array_byte_signal(byte[] value):base(value)
{
}
public override string ToString()
{
return string.Join("; ", Value);
}
}
And this is my program:
static void Main(string[] args)
{
var signals = new List<Signal>();
signals.Add(new scalar_signal(3));
signals.Add(new array_byte_signal(new Byte[] { 0, 1 }));
foreach (var signal in signals)
{
Console.WriteLine(signal.Value); //Compilation error: Value is not defined in Signal
}
}
As you can see I'm able to create a list of different types of signals but I'm not able to access their properties.
I really need to have only one list (or any other collection) with all my signals becuase later on it will be easier to process.
I have to implement one class for each type of signals as they need to implement a custom behavior depending of the type T. T could be also a class representing a complex number, matrix, etc.
I have read about Covariance and contravariance but I do not see how this could help me.
Thank you for your help.
this is because
when you looping
foreach (var signal in signals)
{
Console.WriteLine(signal.Value); //Compilation error: Value is not defined in Signal
}
the type is Signal
which as you now has no property.
what you need to do it ask it if its able to be something else,
foreach (var signal in signals)
{
//#6
if(signal is scalar_signal)
{
var typeCast = (scalar_signal)signal;
Console.WriteLine(typeCast .Value);
}
//#7.2 +
if(signal is scalar_signal valueTypeName)
{
Console.WriteLine(valueTypeName.Value);
}
}
this should help
I am trying to do the following thing:
- From within a 1st method, I am going through a bunch of objects (of same type) and extracting pointers to specific properties into a list
- This list will then be fed to a another method elsewhere in my program at some point in time and has to modify all the properties (as per provided list) of the original objects
In other words, say we have the following class:
public class Something
{
public SomeFlag = False;
public Something()
{
}
}
Somewhere in the system, we have composed a related list of objects into List.
Now, we want to scan through this list and extract into "List< bool> flags" all the flags (by reference?):
List<bool> flags = new List<bool>();
foreach (var stuff in List<Something>)
{
flags.Add(stuff.SomeFlag);
}
Finally, somewhere else, I want to update these flags, but the update should affect the original object:
public static void SetStates(List<bool> myList)
{
// The flag should get set to true by reference in the original object
myList.SomeFlag = True;
}
Using actions could be one way to achive this:
public class Something
{
public bool SomeFlag { get; set; }
}
internal class Program
{
private static void Main()
{
var somethings = new[] {new Something(), new Something()};
var flags = new List<Action<bool>>();
// create your list of 'pointers'
foreach (var something in somethings)
{
flags.Add(x => something.SomeFlag = x);
}
// set them all to true
foreach (var action in flags)
{
action(true);
}
// check the results
foreach (var something in somethings)
{
Console.WriteLine(something.SomeFlag);
}
Console.WriteLine("press any key to exit...");
Console.ReadLine();
}
}
In C#, you cannot save a reference to a property value (like a pointer to the memory location where the value is stored). You only can save a reference to an object which contains this property value.
In your var list = new List<Something>(), you can store those references to the objects.
Note that it's impossible for value types though. If Something is a struct, not a class, then the list will contain copies of the objects, not the references to the objects. So the rest of my answer assumes we're talking about class Something.
You can define a property changing behavior and apply it using the list of the objects.
If you already know at compile time which properties and which values do you need, you can create a lambda and pass it around.
// Define the behavior and get the object list
Action<Something> setter = o => o.Someflag = true;
var objectList = new List<Something>();
// Call your processing method later on
SetProperties(objectList, setter);
void SetProperties<T>(List<T> objects, Action<T> setter)
{
objects.ForEach(setter);
}
If you don't know at compile which properties and which values you will need, then things get much more complicated. You will need to use Reflection to obtain the property descriptors and to set the values.
Here is a simplified example:
// Define the behavior and get the object list
var objectList = new List<Something>();
string propertyName = "SomeFlag";
PropertyInfo pi = typeof(Something).GetProperty(propertyName);
MethodInfo setter = pi.GetSetMethod();
object value = true;
// Call your processing method later on
SetProperties(objectList, setter, value);
void SetProperties<T>(List<T> objects, MethodInfo setter, object value)
{
var arguments = new object[] { value } ;
objects.ForEach(o => setter.Invoke(o, arguments));
}
I have a simple class that is intended for options of an winforms application. There should be a method that reset options to their default values. I know I can add a separate method to take care of this, but the code will be huge (If I add more options to the class) :
public SensorOptions()
{
ShowLabelMax = ShowLabelMin = ShowLabelAvr = ShowReceivedTextBox = true;
ChartMaxValue = 140;
ChartMinValue = -40;
ShowChartMinValue = ShowChartMaxValue = ShowChartAvrValue = ShowChartAvrLine = true;
LogFolder = Environment.SpecialFolder.MyDocuments.ToString();
LoggingEnabled = true;
}
public void ResetOptions()
{
this = new SensorOptions(); //can not do. 'this' is read-only
}
I mean I can copy/paste the code from constructor into ResetOptions() method. But is there any smarter ways to achieve this?
You cannot assign this because you may have references to this instance of your class in your program. If you could re-construct the object by re-assigning this, it would mean that all references to the old instance of the class become invalid.
No matter how many options you have in your class, you initialize each of them one or the other way (because you mention default value in your question - so you need to assign that default value somewhere at least once, probably in the constructor). Therefore, the solution to your problem is simple - move all initializers to the separate method and call it in the constructor, and then also call it every time you need to reset your options to their default values.
If any of your options are not assigned a default value explicitly, and use system default and you don't want to write option=default(optionType) for each option, you can use reflection to enumerate all fields/properties in that class and assign default values to them, like this:
public static object GetDefault(Type type)
{
if(type.IsValueType) return Activator.CreateInstance(type);
return null;
}
foreach(var field in this.GetType().GetFields())
field.SetValue(this, GetDefault(field.FieldType));
foreach(var prop in this.GetType().GetProperties())
prop.SetValue(this, GetDefault(prop.PropertyType));
Move all of the code from the constructor into the ResetOptions method, then in your constructor call the ResetOptions method. Your initialisiation code is only in one place then.
You have very simple architecture for your situation. In my opinion it would be better to apply a trick for this:
you have class for holding all your options (pseudo code):
class AllOptionsBackstage
{
public bool ShowLabelMax { get; set; }
public bool ShowLabelMin { get; set; }
public bool ShowLabelAvr { get; set; }
public AllOptionsBackstage()
{
// apply default values here
}
}
.....
class MyOptions
{
private AllOptionsBackstage _options;
public MyOptions()
{
Reset();
}
public bool ShowLabelMax
{
get{ return _options.ShowLabelMax; }
set{ _options.ShowLabelMax = value; }
}
public bool ShowLabelMin
{
get{return _options.ShowLabelMin;}
set{_options.ShowLabelMin=value; }
}
public bool ShowLabelAvr
{
get{ return _options.ShowLabelAvr;}
set{ _options.ShowLabelAvr = value; }
}
public void Reset()
{
_options = new AllOptionsBackstage(); // will reset all your options to default
}
}
Given the following code;
public class CustomControl {
private object _dataItem;
public object DataItem {
get { return _dataItem; }
set { _dataItem = value; }
}
public void Update(ref string t) {
t = "test";
}
}
public class Consume {
public void Example() {
CustomControl ctrl = new CustomControl();
ctrl.DataItem = anyObject.anyProperty;
string prop = anyObject.anyProperty;
ctrl.Update(ref prop);
anyObject.anyProperty = prop;
}
}
How can I change it so that the DataItem property is itself a reference, allowing you to pre-emptively set it to point to a variable thus allowing you to call Update() without any parameters.
So the Consume class would then look similar to;
public class Consume {
public void Example() {
CustomControl ctrl = new CustomControl();
ctrl.DataItem = anyObject.anyProperty;
ctrl.Update();
// anyObject.anyProperty has been updated to "test"
}
}
So the assigment of anyObject.anyProperty is then handled internally within CustomControl
You need to store the act of setting something to a string, so store an Action<string>:
public class CustomControl {
public Action<string> SetData { get; set; }
public void Update() {
// TODO nullity check
SetData("test");
}
}
Then Consume would look like:
public class Consume {
public void Example() {
CustomControl ctrl = new CustomControl();
// store {the act of setting this property of this object to a string}
ctrl.SetData = s => anyObject.anyProperty = s;
ctrl.Update();
}
}
The Update call will set anyObject.anyProperty to test. Note that you are storing specifically the act of setting this property of the particular anyObject you refer to in the assignment to SetData.
To expand on the lambda: we want to create a value of type Action<string>, that is, a thing which takes a string and returns no result. Such a thing is going to be executable code. Prior to C# 3, to create a 'value' that was executable code, we would have had to do something like:
ctrl.SetData = delegate(string s) { someObject.SomeProperty = s; };
With this syntax it's more obvious that we're creating a method - it has a { } delimited body, it has statements in it, and it's clear there is a string parameter that is used by the body.
One thing achieved by lambda expressions in C# 3 is the ability to condense this down; loosely, the whole of
// not compilable code
delegate(parameters) { body; }
can be replaced with
// not compilable code
(parameters) => body;
and in the case where there's only one parameter
// not compilable code
parameter => body;
which is what we have here: the expression assigned to ctrl.SetData is a piece of behaviour that accepts a string (s) and sets anyObject.anyProperty to that string. The real power is in the way the C# compiler can work out the types to it know we're creating an Action<string>.
At first I didn't understand what you're trying to do. What you're looking for is the Adapter or Facade pattern. That is, you have an object with a particular interface, but you need to adapt it to a different interface or provide a simpler interface.
One way to implement these patterns is to use composition and delegate the new interface to methods on the existing interface.
public interface IUpdatable<U>
{
void Update( U newValue );
}
public abstract class CustomControl<T,U> : IUpdatable<U>
where T : Control
{
private T Control { get; set; }
protected CustomControl( T control )
{
this.Control = control;
}
public abstract void Update( U newValue );
}
public class TextBoxFacade : CustomControl<TextBox,string>, IUpdatable<string>
{
public TextBoxFacade( TextBox textbox ) : base(textbox) { }
public override void Update( string newValue )
{
this.Control.Value = newValue;
}
}
I frequently find myself having a need to create a class as a container for some data. It only gets used briefly yet I still have to create the class. Like this:
public class TempObject
{
public string LoggedInUsername { get; set; }
public CustomObject SomeCustomObject { get; set; }
public DateTime LastLoggedIn { get; set; }
}
public void DoSomething()
{
TempObject temp = new TempObject
{
LoggedInUsername = "test",
SomeCustomObject = //blah blah blah,
LastLoggedIn = DateTime.Now
};
DoSomethingElse(temp);
}
public void DoSomethingElse(TempObject temp)
{
// etc...
}
Usually my temporary objects have a lot more properties, which is the reason I want to group them in the first place. I wish there was an easier way, such as with an anonymous type. The problem is, I don't know what to accept when I pass it to another method. The type is anonymous, so how am I supposed to accept it on the other side?
public void DoSomething()
{
var temp = new
{
LoggedInUsername = "test",
SomeCustomObject = //blah blah,
LastLoggedIn = DateTime.Now
};
// I have intellisense on the temp object as long as I'm in the scope of this method.
DoSomethingElse(temp);
}
public void DoSomethingElse(????)
{
// Can't get my anonymous type here. And even if I could I doubt I would have intellisense.
}
Is there a better way to create a temporary container for a bunch of different types, or do I need to define classes every time I need a temporary object to group things together?
Thanks in advance.
Tuple may be the solution you're looking for.
public void DoSomething()
{
var temp = Tuple.Create("test", "blah blah blah", DateTime.Now);
DoSomethingElse(temp);
}
public void DoSomethingElse(Tuple<string, string, DateTime> data)
{
// ...
}
The rules state that
You cannot declare a field, a property, an event, or the return type
of a method as having an anonymous type. Similarly, you cannot declare
a formal parameter of a method, property, constructor, or indexer as
having an anonymous type.
Personally, I would just bite the bullet on this one to preserve compile time integrity.
The Tuple is the clean way to go, but just to let you know that C# doesn't let you down even otherwise and to answer the question, this is how DoSomethingElse could look like:
private static void DoSomething(object temp)
{
var typedTemp = CastToType(temp, new
{
LoggedInUsername = "dummy",
SomeCustomObject = "dummy",
LastLoggedIn = DateTime.Now
});
Console.WriteLine(typedTemp.LastLoggedIn);
}
private static T CastToType<T>(object obj, T type)
{
return (T) obj;
}
PS: Don't -1, I won't use this, I don't ask you to use this :)
You can pass around anonymous types by declaring the parameter dynamic under C# 4. That said, I would not recommend this except in private methods. You lose type-safety, IntelliSense, and readability.
You could also use non-generic container classes such as ArrayList. But then you're back to casting, which is why we got generics in the first place.
Personally I'd create the class. Look to see if there's an abstraction that covers all your types and declare that as an interface, then use a generic container of that type.
public class GenericObjs
{
private List<object> objs = new List<object>();
public List<object> Objs { get { return objs; } set { objs = value; } }
public GenericObjs(List<object> Objs) { objs = Objs; }
}
You could include List String and a constructor for List String ...
I just don't come across the need for throw away classes. If the business object has structure then a class is the way to define and enforce that structure and it is not much code.