Keep old object without changing it - c#

I have the following code and In RT when mappingObject is updated oldObjToDel is updated accordingly, but my question is :
Is there a way to keep the oldObjToDel with the first reference without changing it like it happens after calling to the updateReferance method ? I want oldObjToDel to keep the object before changing it in UpdateReferance...
private bool UpdateMapping(out MappingFields oldObjToDel)
{
MappingFields mappingObject = GetMappingLabelObject(textbox.Name);
oldObjToDel = mappingObject;
isAdded = UpdateReferance( mappingObject);
}
internal class MappingFields
{
public string Type { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public bool isFound { get; set; }
}

There is no way to do this automatically in the general case. You need to make a copy (clone) of the object, which would be independent of its "source".
If your object only has scalar fields then you can utilize object.MemberwiseClone; otherwise, you should consider implementing ICloneable and supply an implementation of Clone with appropriate semantics. The documentation for MemberwiseClone also lists several alternatives:
There are numerous ways to implement a deep copy operation if the
shallow copy operation performed by the MemberwiseClone method does
not meet your needs. These include the following:
Call a class
constructor of the object to be copied to create a second object with
property values taken from the first object. This assumes that the
values of an object are entirely defined by its class constructor.
Call the MemberwiseClone method to create a shallow copy of an object,
and then assign new objects whose values are the same as the original
object to any properties or fields whose values are reference types.
The DeepCopy method in the example illustrates this approach.
Serialize the object to be deep copied, and then restore the
serialized data to a different object variable.
Use reflection with
recursion to perform the deep copy operation.
Update:
Since your implementation of MappingFields only uses string and boolean fields, MemberwiseClone will do the job. First expose a Clone method:
internal class MappingFields : ICloneable
{
public string Type { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public bool isFound { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
and then call it:
oldObjToDel = (MappingFields)mappingObject.Clone();

You could use AutoMapper to create a clone of the original object easily. I guess this post could give some idea on how to do it. You could also check AutoMapper getting started page.
Hope I helped!

Related

C# Concurrent Dictionary Object Read/Update Thread Safety Question

In the code below I have a concurrent dictionary that i'm using for storing a single key/value pair where the value is a collection of strings.
I will be reading and updating the strings in this single key/value pair from different threads.
I'm aware that concurrent dictionaries are not entirely thread safe if one thread has changed a value before the other thread has perhaps finished reading it. But equally i'm not sure if string values really come into this topic or not, could someone please advise?
Its also worth mentioning that although I put this "GetRunTimeVariables" method into an interface for dependency injection, I actually cant use DI all the time for accessing this method due to the stages of app startup and OIDC events sign in/out where i need to access the dictionary values within classes that can't use dependency injection, so in essence I could be accessing this dictionary from nay means as necessary throughout the lifetime of the application.
Lastly i'm not really sure if there is any benefit in pushing this method into an interface, the other option is simply new up a reference to this class each time i need it, some thoughts on this would be appreciated.
public class RunTimeSettings : IRunTimeSettings
{
// Create a new static instance of the RunTimeSettingsDictionary that is used for storing settings that are used for quick
// access during the life time of the application. Various other classes/threads will read/update the parameters.
public static readonly ConcurrentDictionary<int, RunTimeVariables> RunTimeSettingsDictionary = new ConcurrentDictionary<int, RunTimeVariables>();
public object GetRunTimeVariables()
{
dynamic settings = new RunTimeVariables();
if (RunTimeSettingsDictionary.TryGetValue(1, out RunTimeVariables runTimeVariables))
{
settings.Sitename = runTimeVariables.SiteName;
settings.Street = runTimeVariables.Street;
settings.City = runTimeVariables.City;
settings.Country = runTimeVariables.Country;
settings.PostCode = runTimeVariables.PostCode;
settings.Latitude = runTimeVariables.Latitude;
settings.Longitude = runTimeVariables.Longitude;
}
return settings;
}
}
Class for string values:
public class RunTimeVariables
{
public bool InstalledLocationConfigured { get; set; }
public string SiteName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostCode { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
}
The System.String type (the classical strings of C#) is immutable. No one can modify the "content" of a String. Anyone can make a property reference a different String.
But in truth the only problem you have here is that the various values could be de-synced. You have various properties that are correlated. If one thread is modifying the object while another thread is reading it, the reading thread could see some properties of the "old" version and some properties of the "new" version. This isn't a big problem if the object once written to the ConcurrentDictionary is not changed (is "immutable" at least as a business rule). Clearly a correct solution is to have RuntimeVariables be an immutable object (composed only of readonly fields that are initialized at instancing for example)

Mapping Collections in Automapper

I'm using Automapper to clone an object. I have a class which contains collections that I want handled in a non-standard way, which I'll explain below (I've stripped out a bunch of code to highlight the specific issue):
public class CommunityModel
{
private readonly IUIManaer _uiMgr;
private readonly IMapper _mapper;
private ValidatedCollection<CommunityUserModel, string> _users;
private int _communityIndex = -1;
public CommunityModel( IUIManager uiMgr, IMapper mapper, IElementManager<CommunityUserModel, string> userMgr )
{
_uiMgr = uiMgr ?? throw new NullReferenceException( nameof(uiMgr) );
_mapper = mapper ?? throw new NullReferenceException( nameof(mapper) );
Users = new ValidatedCollection<CommunityUserModel, string>( userMgr );
}
public int CommunityIndex
{
get => _communityIndex;
set
{
if (value < -1) value = -1;
Set(ref _communityIndex, value);
IsNew = value < 0;
}
}
public ValidatedCollection<CommunityModel, string> Collection { get; set; }
public ValidatedCollection<CommunityUserModel, string> Users
{
get => _users;
set
{
ChangeTracker.RegisterCollection(value);
SetAndValidate( ref _users, value );
}
}
}
ValidatedCollection<> is an extension of WPF's ObservableCollection. The CommunityIndex property uniquely identifies a CommunityModel instance. This allows me to use the Automapper.Collection extensions via the EqualityComparison() extension method.
I don't want Automapper to initialize the Users collection, because it gets initialized in the class constructor. But I want the elements of the User collection to be cloned from the source Users collection to the destination Users collection.
The Collection collection contains a list of CommunityModel objects, including the instance which has the Collection property (i.e., Collection is a set of sibling CommunityModel instances). I'd like Automapper to initialize the collection, and, ultimately, copy all of the CommunityModel siblings other than the source object to that collection, and then add the destination object to the collection (i.e., in the end, Collection will be a set of sibling CommunityModel objects, with the source CommunityModel replaced by the destination CommunityModel).
My map is currently defined as follows:
CreateMap<CommunityModel, CommunityModel>()
.ForMember(dest=>dest.Users, opt=>opt.Ignore())
.ForMember(dest=>dest.Collection, opt=>opt.Ignore() )
.EqualityComparison((x,y)=> x.CommunityIndex == y.CommunityIndex);
CreateMap<CommunityUserModel, CommunityUserModel>()
.EqualityComparison((x,y) => x.UserIndex == y.UserIndex);
If I don't Ignore() the Users collection, Automapper will initialize the collection, which overrides the required configuration of Users set in the constructor and causes problems elsewhere in my app. But if Ignore() the Users collection, its elements are never cloned from source to destination. What I want to do is not have Automapper initialize Users, but still clone the contents.
If I don't ignore the Collection collection, I get an infinite loop and stack overflow, I believe because cloning Collection's elements involves creating an instance of the CommunityModel which owns the Collection property, which should be a reference to the destination object being created, but instead leads to the creation of another identical destination object. What I'd like to do is have Automapper initialize the Collection collection, but >>not<< clone the source elements, which I guess I'd have to do later in an AfterMap() call.
I realize this is somewhat arcane, but the overall design of my project results in these requirements.
What is the best way of doing this within Automapper? Should I look into creating a custom value resolver, even though I'm cloning an object, so the property names are identical between source and destination?
I'm going to describe how I resolved my issue, but I'm not going to mark it as an answer, because I'm not familiar enough with Automapper to know if what I think it's doing is what it's actually doing.
What appears to be happening, when Automapper maps collections -- even with the Automapper.Collections library installed and activated -- is that collections are deemed to be "different", even if the types of the elements in the source and destination collections can be automatically mapped, if the source and destination collection types are different.
For example, if the source Community object has a List<> of CommunityUsers:
public class Community
{
public string Name { get; set; }
public string SiteUrl { get; set; }
public string LoginUrl { get; set; }
public List<CommunityUser> Users { get; set; }
}
public class CommunityUser
{
public string UserID { get; set; }
public string VaultKeyName { get; set; }
}
and you want to map it to destination objects like this:
public class CommunityModel
{
// omitting constructor, which contains logic to
// initialize the Users property based on constructor arguments
public string Name {get;set;}
public string LoginUrl {get;set;}
public string SiteUrl {get;set;}
public ValidatedCollection<CommunityUserModel, string> Users
{ get; set;}
}
public class CommunityUserModel
{
public string UserID {get; set;}
public string VaultKeyName {get;set;}
}
even though all the property names are "recognizable" by Automapper, and the two Users collections are both IEnumerable, the fact that the two collections are of different types apparently causes Automapper to treat the collections as "different".
And that apparently means the add/delete/copy logic of Automapper.Collections doesn't get used, even if present. Instead, Automapper tries to create an instance of (in this case) ValidatedCollection, populate it from the source object collection, and then assign it to destination object collection.
That's fine if ValidatedCollection<> doesn't have required contructor arguments. But it'll fail if it does. Which is what happened in my case.
My workaround was to do this in the Mapper definition:
CreateMap<Community, CommunityModel>()
.ForMember(dest=>dest.Users, opt=> opt.Ignore())
.AfterMap( ( src, dest, rc ) =>
{
foreach( var srcUser in src.Users )
{
dest.Users.Add(rc.Mapper.Map<CommunityUserModel>(srcUser));
}
} );
This keeps Automapper from doing anything with the destination Users property (which is initialized in the CommunityModel constructor), and maps over the source User objects after the "automatic" mapping is done.

ReadonlyCollection, are the objects immutable?

I'm trying using ReadOnlyCollection to make object immutable, I want the property of object are immutable.
public ReadOnlyCollection<FooObject> MyReadOnlyList
{
get
{
return new ReadOnlyCollection<FooObject>(_myDataList);
}
}
But I little confused.
I tried to change the property of the object in to MyReadOnlyList using a foreach and ... I can change value property, is it correct? I understood ReadOnlyCollection set an add level to make the object immutable.
The fact that ReadOnlyCollection is immutable means that the collection cannot be modified, i.e. no objects can be added or removed from the collection. This does not mean that the objects it contains immutable.
This article by Eric Lippert, explains how different kinds of immutability work. Basically, a ReadOnlyCollection is an immutable facade which can read the underlying collection (_myDataList), but cannot modify it. However, you can still change the underlying collection since you have a reference to _myDataList by doing something like _myDataList[0] = null.
Furthermore, the objects returned by ReadOnlyCollection are the same ones returned by _myDataList, i.e. this._myDataList.First() == this.MyReadOnlyList.First() (with LINQ). This means that if an object in _myDataList is mutable, then so is the object in MyReadOnlyList.
If you want the objects to be immutable, you should design them accordingly. For instance, you might use:
public struct Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
// In C#6, the "private set;" can be removed
public int X { get; private set; }
public int Y { get; private set; }
}
instead of:
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
Edit: in this case, as noted by Ian Goldby, neither struct allows you to modify properties of the elements in the collection. This happens because structs are value types and when you access an element the collection returns a copy of the value. You can only modify the properties of a Point type if it is a class, which would mean that references to the actual objects are returned, instead of copies of their values.
I tried to change the property of the object in to MyReadOnlyList
using a foreach and ... I can change value property, is it correct? I
understood ReadOnlyCollection set an add level to make the object
immutable.
Using a ReadOnlyCollection does not make any guarantees as for the object that is stored in the collection. All it guarantees is that the collection cannot be modified once it has been created. If an element is retrieved from it, and it has mutable properties, it can very well be modified.
If you want to make your FooObject an immutable one, then simply do so:
public class FooObject
{
public FooObject(string someString, int someInt)
{
SomeString = someString;
SomeInt = someInt;
}
public string SomeString { get; };
public int SomeInt { get; };
}
What is immutable is the collection itself, not the objects. For now, C# doesn't support immutable objects without wrapping them as ReadOnlyCollection<T> does in your case.
Well, you can still create immutable objects if their properties have no accessible setter. BTW, they're not immutable at all because they can mutate from a class member that may have equal or more accessibility than the setter.
// Case 1
public class A
{
public string Name { get; private set; }
public void DoStuff()
{
Name = "Whatever";
}
}
// Case 2
public class A
{
// This property will be settable unless the code accessing it
// lives outside the assembly where A is contained...
public string Name { get; internal set; }
}
// Case 3
public class A
{
// This property will be settable in derived classes...
public string Name { get; protected set; }
}
// Case 4: readonly fields is the nearest way to design an immutable object
public class A
{
public readonly string Text = "Hello world";
}
As I said before, reference types are always mutable by definition and they can behave as immutable under certain conditions playing with member accessibility.
Finally, structs are immutable but they're value types and they shouldn't be used just because they can represent immutable data. See this Q&A to learn more about why structs are immutable: Why are C# structs immutable?

Produce different serialized JSON for a given class in different scenarios

Update 1: for reasons I won't go into, I want to avoid having anything other than the properties to be persisted in my entity objects. This means no extra properties or methods...
I have an entity called Entity1 with (say) 10 public properties. In
one place in my code I want to output serialized JSON with (say) 3 of
those fields, in a second place I need to output 7 fields and in a
third place I might need to output (say) all 10 fields. How do I do
this using Newtonsoft's JSON library?
I can't use [JsonIgnore] or [DataMember] as that will apply to all
cases, so I won't be able to create "custom views" of the data (my own
terminology :-).
I tried to achieve this using an interface:
public interface Entity1View1
{
string Property1;
string Property2;
string Property5;
}
had Entity1 implement Entity1View1 and I passed an
IList<Entity1View1> to the JSON serializer (the objects were
actually just Entity1 objects). Didn't work: the serializer output
all the 10 public properties of Entity1.
The only other way I could think of was to implement
Entity1Wrapper1, Entity1Wrapper2 etc. type of classes where each
object would hold a corresponding instance of Entity1 and in turn
expose only those public properties that correspond to the properties
I want to show in "View1", "View2" etc. Then I pass lists of these
wrapper objects to the serializer (should work, haven't tried it yet).
Is there a better way?
If it matters, here's my configuration:
.Net 4.5
MVC 5
Don't know it that's the best way... but that's one.
One good point is that it will work either with json serialization or xml serialization, for example (which you may don't mind at all).
You can use ShouldSerialize<yourpropertyName> to manage what is serialized or not. <yourpropertyName> must match exactly the name of the property you wanna manage.
For example
public class Entity {
//assuming you want the default behavior to be "serialize all properties"
public Entity() {
ShouldSerializeProperty1 = true;
ShouldSerializeProperty2 = true;
ShouldSerializeProperty3 = true;
}
public string Property1 {get;set;}
public bool ShouldSerializeProperty1 {get;set;}
public string Property2 {get;set;}
public bool ShouldSerializeProperty2 {get;set;}
public int Property3 {get;set;}
public bool ShouldSerializeProperty3 {get;set;}
}
Then you could do, before all your serialization (of course, this could / should be extension methods).
var list = myListOfEntity;
//serialization1
foreach (var element in list) {
element.ShouldSerializeProperty3 = false;
}
//or serialization2
foreach (var element in list) {
element.ShouldSerializeProperty2 = false;
element.ShouldSerializeProperty3 = false;
}
I just wanted to make sure that this was the final step in processing.
You can create anonymous objects to serialize based on circumstance:
var json1Source1 = new {
Property1 = entityView1.Property1,
Property3 = entityView1.Property3
};
var json1Source2 = new {
Property2 = entityView1.Property2,
Property3 = entityView1.Property3
};
You can create jsonSource1 (or 2, 3, 4 etc) as anonymous objects that capture just what you need and then serialize them. The serializer will not care that they are anonymous.
Update 1:
To conditionally serialize a property, add a method that returns boolean with the same name as the property and then prefix the method name with ShouldSerialize..
This means that the solution suggested by Raphaël Althaus doesn't work as it relies on properties, whereas the serializer's documentation mentions that it has to be a method. I have verified that only a method returning a bool works as expected.
Original:
I finally went with a mix of Wrapper classes and the methodology suggested by Raphaël Althaus (with modifications): use Wrappers where some amount of sophistication may be required and use Raphaël's suggestion when simplicity will do.
Here's how I am using wrappers (intentionally left out null checks):
public class Entity1View1
{
protected Entity1 wrapped;
public Entity1View1(Entity1 entity)
{
wrapped = entity;
}
public String Property1
{
get { return wrapped.Property1; }
}
public String Property2
{
get { return wrapped.Property2; }
}
public String Property3
{
get { return wrapped.Property3.ToUpper(); }
}
}
This allows me to modify properties as their values are returned (as done with Property3 above) and lets me leverage inheritance to create new ways of serialization. For example, I can flatten the structure/hierarchy:
public class Entity1View2 : Entity1View1
{
pulic Entity1View2(Entity1 entity) : base(entity) { }
public long? SubEntityID
{
get { return wrapped.SubEntity.ID; }
}
}
For simpler cases where complexity/transformation of this sort is not required, I can simply use the ShouldSerialize* methods.
Same entity classes, different serialization outputs.

What is it called when a class property is an instance of another class?

Very basic question here, look at my property Order in my customer class. Wondering what is the formal name of a property type like this is (yes, this could also be a list).
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public Order Orders { get; set; } // what am i called?
}
public class Order
{
public int ID { get; set; }
public string SomeProperty { get; set; }
}
Its the same thing. Its called a "Property". There is no different name for it. Consider your SomeProperty which is of type string. string is also a class and SomeProperty is its object. Same convention with your class would follow as well.
From C# Language Specification.
1.6.7.2 Properties
A property is declared like a field, except that the declaration ends
with a get accessor and/or a set accessor written between the
delimiters { and } instead of ending in a semicolon.
So the term "property" in C# is associated with the accessors (get/set)
from ECMA-334 8.7.4:
A property is a member that provides access to a characteristic of an object or a class.
It doesn't matter what type the property accesses. The property itself is just to provide access to it.
So, bottom line, a property is a property no matter what type it accesses.
It's just a property - there's not a formal name for it.
The concept itself is called Composition. Basically, you want to be able to use a Customer object to get information about an Order, but you don't want the logic that gets that information to live in Customer. So, you have a member who is an Order and Order encapsulates the Order behavior.
You could say that a Customer is composed of Order along with other values.
Have a link: http://www.javaworld.com/jw-11-1998/jw-11-techniques.html
Not that you asked this, but you probably will want an actual collection of Orders. You could start with
public List<Order> Orders;
It's still a property. It just gets/sets an object, which is an instance of a class.

Categories