How to get ObjectId of the recently modified object?
I add some polyline to the drawing. Each one is the same. When one modifies the other, they must also be adjusted to the changes. I need to exclude from the list of objects that need to be updated, the object I just modified. I can not find the answer.
Example:
I have some polyline. When creating them, an event handler is added (ObjectId of each object is added to NOD). At the moment of modifying one of them, the function assigned to the modification will loop through all objects stored in NOD. When the length is changed other objects must also do so. Initially I want to do that the rest will be removed and replaced with a modified copy of the object.
Here I need to access the last modified object to be able to skip it while modifying other polyline. At the moment, the program ends and I think this is a problem because I'm trying to convert the polylines to the same one.
If I understand your problem correctly, what you need is a dynamic exclusion list. A Hashset<ObjectID> instance will serve you well, as ObjectID is a struct (i.e. a value type). See this tutorial:
HashSet is an unordered collection that contains unique elements. We can apply various operations on a HashSet like, Add, Remove, Contains etc.
Once a polyline is modified by user, I am assuming an event triggers your process to go ahead and modify all other polylines in your NOD. To utilize your exclusion list, add a private field to the class that contains your Command Methods:
private static HashSet<ObjectId> exclusionList = new HashSet<ObjectId>();
Make sure to add the ObjectID of the polyline that the user modified to the exclusionList right away:
exclusionList.Add(modifiedObjectID);
The Add() method returns true if the list does not contain the objectID you tried to add, and adds it to the set. It will return false if the set already contains the ObjectID. This is the key to solving your issue. You add each entity to the exclusion set so that each one is only modified once per cycle. Also, since you already added your original polyline's ObjectID to the set, it will never be modified in the loop. After the loop ends, clear the list and wait for the next time the user modifies an entity.
In your loop that cycles through your MOD, do the following:
public void ProcessEntities()
{
foreach(DBDictionaryEntry obj in MyNOD)
{
//Add each objectID to your exclusion List
//if it's already there, everything inside the if statement is skipped!
if(exclusionList.Add(obj.Value))
{
//do your object modification here
}
}
//All entities have been processed now
//clear the list and wait for the next event
exclusionList.Clear();
}
Related
I am building a control in xamarin forms that binds to a list of objects. To get this binding to work I need to use observable collections (otherwise propertychanged methods don't fire).
I noticed a really frustrating interaction as a result of needing to use OC's as opposed to lists. Whenever the binded OC updates, the values in my controls are automatically updated, even if they are just references of the OC, Here is how i am copying the OC.
//Internal list of events
private List<EventItem> _events;
void OnEventsChanged(ObservableCollection<EventItem> eventsCollection)
{
//Error handle
List<EventItem> events = eventsCollection.ToList();
//Do something
_events = events;
}
The problem comes when the OC updates, I want to check for new/deleted AND altered objects. The issue is that when the OC updates, it is updating the internal list (_events) aswell. This means when I go to do comparisons between the old & new values, they are the same.
Honestly I don't really understand how c# handles copying references of objects around, I had a similar issue a while back with DateTime.Now being calculated as opposed to copying the value of the already initialised object.
var time = DateTime.Now;
await Task.Delay(1000);
var time2 = time; //This is 1 second later than time, not the value of time (which is what I wanted)
I have used Objective-C in the past and that has the concept of MutableCopy where you can assign a new list from an existing one, they have the same values but aren't linked.
How can I do this in C# so that my controls internal list is only updated by me and not the OC?
Thanks
That's perfectly normal. If I have enough time, I'll try to explain it to you.
In a nutshell, the observableList (or a List) is a list of reference to the objects and not a list of objects. The thing is that the objects are not copied inside a list but the list contains a reference to the different objects. That means that if you do something like ToList(), you get another list of references to the exact same objects.
Now to solve your problem. Just create a new list with new objects with something like
var newList = oldList.Select(x => new Model(x)).ToList();
And of course the Model class has a constructor that accept a Model as a parameter and copy the properties.
When you write _events = events;, you create not a new object, but a reference for the same object. https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/index .
You should to clone (create a copy of object itself) as it mentioned in comment by #Matt.
I am building a custom small interpreted script language and everything is working just fine except the scoping.
For the actual execution I am using a visitor pattern:
I modified the pattern to pass through the Variable Table:
public void visit(ProgrammTree proTree){
VariableTable vt = new VariableTable();
foreach (var t in proTree.getChildren()) {
t.accept(this, vt);
}
}
And here is where the problem starts:
public void visit(WhileTree whiletree, VariableTable vt) {
var cond = (ConditionTree)whiletree.getChild(0);
while (cond.accept(this, vt).toBoolean()) {
var clonedSubTable = new VariableTable(vt)
foreach (Tree t in whiletree.getChildren()) {
t.accept(this, clonedSubTable );
}
}
}
Problem is that changes within the loop are not performed in the outer scope.
Do you have a smart way to implement this?
You left a couple of things a bit vague, so I'm going to make the following assumptions (please point out any that are wrong):
Your VariableTable maps variable names directly to their associated value
Whenever you assign a value, you directly set that value as the entry in the table (without going through any layer of indirection)
Your cloned variable tables do not keep a reference to the original and don't propagate any changes to the original
So under these assumption the problem is that any assignments done using the cloned table won't be visible in the original table even in cases where the assigned-to variable was already present in the original table.
To fix this, there are multiple approaches:
You can make your table map variables to memory locations rather than values. You'd then have another table (or just a plain array) that maps memory locations to values. This way the table-entry for a variable would never change: Once the variable is defined, it gets a memory address and that address isn't going to change until the variable dies. Only the value at the address may change.
A quick-and-dirty alternative to that approach that keeps you from having to manage your own memory would be to add a mutable wrapper around your values, i.e. a ValueWrapper class with a setValue method. Assuming that your cloned table is a shallow copy of the original, that means that you can call setValue on an entry of the cloned table and, if that entry was already present in the original table, the change will also be reflected in the original table.
The solution that keeps closest to your current code would be to turn your table into a linked structure. Then new VariableTable(vt) would not actually copy anything, but simply create a new empty table with a parent link pointing to the original table. Any new entries would be inserted into the new table, but accesses to old entries would simply be propagated to the parent table.
Even if you choose to go with options 1 or 2 to solve your current problem, using a parent link instead of copying the table constantly would be a good idea anyway for performance reasons.
The downside of only going with solution 3 would be that you'll run into similar problems again when you implement closures. So it really only fixes your exact current problem.
The upside of solution 1 is that it allows you full control over your memory, so you have free hand in implementing features related to memory in any way you want. The down side is the same.
In my app, I store objects(of Class1) on two lists (of type List<Class1>).
The first list is used to store all the objects added in the app while the other list filters few of the objects based on a filtering function.
Both the lists are part of a class file(Class2) which I store in the app data using IsolatedStorage.ApplicationSettings .
When I access an object in the app, the object is extracted from the list and on changing any of its property, I click on a 'done' button.
done_event
{
remove the object from the first list;
remove it from the second list based on a simple condition (#2);
change its properties;
add the new object back to the first list;
run the filtering function to add the new object to the second list if necessary;
}
Everything works fine when I am using it after installing it on the emulator/device but once I exit the app and open it back again and change a property of an object, the new object is removed and added in the first list, however, it is not removed from the second list (the second list populates with two objects instead of one, I used breakpoints and figured out the object was not getting removed from the second list at step #2).
I am new to using IsolatedStorage, so don't know the drawbacks. Please help
I don't know how you load the objects of the two lists after a restart of the app, but maybe the ApplicationSettings deserializes your objects two times for the two lists so you have two different objects.
Try something like a proxy for the ApplicationSettings like the following example to keep only one valid list of all stored Class1-instances:
public List<Class1> Class1List
{
get
{
if(this.class1List == null)
{
if(this.applicationSettings.Contains("class1Key"))
this.class1List = (List<Class1>)this.applicationSettings["class1Key"];
}
return this.class1List;
}
set
{
this.applicationSettings["class1Key"] = value;
this.applicationSettings.Save();
}
}
I have a class contains a lot of properties. One of them needs a special UI to be edited.
The user may press edit to this property in the UI then he make changes and either press OK or Cancel
e.g.
class A{
private List<Employee> employees;
public void EditMyEmployees(){
EmployeeEditorForm editor = new EmployeeEditor(employees);
if(editor.ShowDialog() == DialogResult.OK){
employees = editor.GetEditedEmployeesList();
}
}
}
The problem in the previous code that the editor has a copy of the reference to the employees List
and when the editor makes any edits in the List it will be reflected in the original object.
So, pressing OK or Cancel will have the same effect (the object is already updated) and no need for the step
employees = editor.GetEditedEmployeesList();
I know that making deep copy for the employees array before sending it to the editor will solve the problem but still I think this is not the efficient way to do it
I am looking for a design pattern that can make this in a better way.
You don't necessarily need to deep copy the whole collection. You just need to keep track of the elements that changed. Within your EmployeeEditor, use three lists (List<Employee> to keep track of:
Added employees
Removed employees
Changed employees
Upon Cancel, you would need to remove the "added" items, add back the "removed" items, and replace the changed items with their original state.
Note that the changed employees list would need to keep a copy of the original state of the object. If the Employee class has some sort of unique id, you can match cased on that id. Otherwise, the "changed" list would need to be a List<Tuple<Employee, Employee>> so that you can store the matching items.
Also note that, when changes happen in the employees list, you also need to make necessary changes in those three lists. For example, if an new employee is added and then removed, you also need to remove that record from the "added" list. Or it is possible an employee is changed and then removed, in which case you also need to remove from "changed" list.
Having said all this, if I were you, I would make a decision based on the expected use cases and real performance problems (not anticipated performance issues). It is very likely that simply deep copying your collection is the simplest and least error prone way.
There are two kinds of changes involved here: (1) changes to the list (Add / Remove) and (2) changes to individual elements of the list (employees in this case).
Now, part of the problem comes from the semantics of OK/Cancel. If you restrict the scope of these two buttons to changes of the second kind (i.e., changes to the elements of the list), you will be able to handle Remove with a confirmation dialog on this particular action ("Remove such and such"?). For the Addition you don't need anything special, just add a new element to the list. If the user changes their mind they will still have the Remove action available.
For changes on a particular element (second kind) you can use the command pattern as mentioned in the comment. More simply, you could initialize temporary variables for all the fields your editor displays from the element under edition. As the user modifies some values your editor will update the corresponding temporaries. If the user press Cancel you will simply forget those changes (or reinitialize them from the element). If the user press Apply (yes, you should include the Apply button also,) you will now write each of the temporary values onto the corresponding element's attribute. If the user hits OK you would Apply and Close.
I'm writing a 2D infinite Terrain Editor with focus on performance. Each time the user paints, he creates Nodes which at the moment are assigned to Dictionaries in "Layer" classes. Since the user can paint over existing nodes while he's on a different Layer, I want to find those nodes and destroy them. With my current setup this would involve looping through all the Layers and getting the necessary nodes one by one from the dictionaries.
Obviously, this is way too expensive if done tens of thousands of times per frame. So now I thought I could create just one Dictionary with all the nodes in lists. However, this turns out to use almost as much performance as the previous setup, because now I have to perform a check for whether a Key already exists when instantiating new Nodes :
before:
public Node(){
dic.Add(key,this);
}
now:
public Node(){
List<Node> nodes;
if(dic.TryGetValue(key,out nodes))
nodes.Add(this);
else{
list = new List<Node>();
dic.Add(key,list);
}
}
As you can see, while the current setup saves some performance when checking for nodes, it completely ruins the effect by inflating the instantiation time by the dictionary lookup time.
So now I'm looking for some way to get the same effect as Dictionary<Key,List<Node>> , but without the cost of looking up the list in the dictionary. Is there perhaps a different type of dictionary that lets one stack an infinite (or if necessary a limited) number of Values per Key?
Alternatively, is it possible to somehow order the values in the dictionary so I could use a normal Dictionary<key, Node> and then look up the first key and loop from there through all the values until I hit some Node which no longer fits the search criteria?
In pseudo code, my instantiation functions would look like this :
public Node(){
dic.Add(key+LayerIndex,this);
}
and my lookup function would look something like this
public LookUpAll(key, out list){
var o = dic[key]; // looking up just one node
list.Add(o);
var keyPosition = o.keyPosition;
while(o.position == keyPosition){ // then looping through all other nodes at that position until one comes that has a different position.
o = dic.NextValue();
list.Add(o);
}
}
Now, this does not work as is on the unsorted dictionary, but since I was hoping that someone here could maybe get some inspiration from it and work out a working solution.
How do I reduce the number of lookups in my scenario, or add multiple values per key without looking up the key first?
Since the user can paint over existing nodes while he's on a different
Layer,
I'm going to assume that this is so that you do not end up persisting data that you don't need. But what if the user doesn't intend on deleting data on that layer? He just wants to "see" how something looks. Then he undoes his change and blammo, you have no data on the change he just did so you can't undo it.
Why not just keep all the nodes unless the user explicitly tries to delete them? The end user can always choose what is frustum culled in his end result.
You could also try using a tree-like structure.
If you only care about the topmost node related to a certain key, and on occasion need to iterate over all nodes you could construct a linked list from your nodes. This allows you to iterate over nodes and retrieve the relevant node by key. However it increases the memory consumption of your nodes. You could minimize this by creating a subclass of Node that holds a Next property while leaving the normal nodes without the possibility of an underlying node. This might slow down iteration though.
public Node Next { get; set; }
public Node()
{
Node next;
if (dic.TryGetValue(key, out next))
this.Next = next;
dic[key] = this;
}