Populating A New Object With Existing Objects Data - c#

I have a service that is returning a custom object called "UserSettings" In my application I want to add more properties to the "UserSettings" object so I created a new object called "MyUserSettings" that inherits from "UserSettings" now I want to populate my new object with the existing data held in "UserSettings" and the new data I have for my new properties. I do not want to have to map each property one by one to the same property in the new object like this..
_MyUserSettings.Name=_UserSettings.Name;
Is there a way or better approach to what I am doing to populate ALL the properties of the existing object into my new object in one shot??

Yes, you can use Copy Constructor pattern. It would give you an other benefit - you do not need public property setters so object becomes immutable.
public MyUserSettings(UserSettings baseSettings)
{
// TODO: set all properties
}

Unfortunately this is the only way, however, the specific mechanism can change. There are a numerous ways (not listing them all):
Copy constructor, that takes an item and does this manual copying of fields across.
Use reflection to have a more generic mechanism of achieving the same.
Use something like AutoMapper.
They all boil down to pretty much doing the same thing.
If the UserSettings is actually a MyUserSettings then you can simply cast it:
var mySettings = (MyUserSettings)settings;
However, this will fail if UserSettings is really UserSettings.

Related

C# - Can a Method Examine Another Method's Use of a Parameter?

I have a variety of methods that use a configuration object to fill in placeholders in a template. Different methods use different subsets of properties of the configuration object. I'd like an easy way to check that all the properties a given method uses are present in a given config object.
Right now I have a method like this:
private static void ValidateConfiguration(CustomerConfiguration config, params string[] properties)
This has the maintenance disadvantage that it relies on a separate set of strings for the properties used. What I'd love to do is have the validation method look at the calling method and see what properties of the config object are being accessed. Can this be done?
(I could also wrap String.Replace() in a method that checks for nulls, but that's less fun.)
A type safe way to handle your problem would be to implement several interfaces with different meaningful subsets of properties. My understanding is that the presence/absence of the properties in your case depends on the type of configuration object and is dynamic.
you could use a signature like that
ValidateConfiguration<T>(CustomerConfiguration config)
where T represent the interface and use reflection to list the required properties. While it would be practically impossible to parse the code of a method to infer its usages of a data structure, reflection on types (to extract properties) is fairly easy.
Different methods use different subsets of properties of the configuration object.
If you're only creating one instance of the configuration property, then the properties it needs to have are whichever ones are going to be used by any method. In other words, if at least one method needs that property, then the object needs that property.
In that case there's no need to validate it in relation to individual methods that need it. All of its properties need to be populated because they're all needed somewhere. If they're not needed anywhere, you can delete them.
Then, instead of validating that object based on the needs of a particular method, you validate it once, perhaps at startup. All of the properties are needed, so if they haven't been specified then the application just can't run. (Sometimes it's good to include defaults in your configuration object. You might have one property that you want to be able to configure, but in real life it's never going to change.)
If you're creating different instances of the same object for use in different methods and you only want to populate certain properties then it's better not to do that. Just create more granular objects for different scenarios containing all the properties you need.
What frequently happens is this: We have an object with lots of properties and we only use a few of them, so we populate those properties and pass the object to a method. The other properties are null.
Then, someone modifying that method decides that they need another property, so they try to use it, and they're surprised to find out that it's null. Then they have to go back and trace where that object was created and figure out what is populated or not. That's confusing and time-consuming.
Unless fields are entirely optional and it doesn't matter whether they are populated or not, we don't want to find ourselves looking at an object with lots of properties and guessing which ones have been populated because individual methods that create the object "know" which properties other classes do or don't need.

Copy an object from a list into another object in the same list

I have defined a list of objects as List<NewLayerCounterMethod> NewLayer = new List<NewLayerCounterMethod>(); where each object within the class NewLayerCounterMethod has four properties such as: VehicleType, VehicleCounter,Counter,Updating.
The number of objects NewLayer is 10 and I want to copy NewLayer[7] into NewLayer[5] such that if NewLayer[7] is changed, NewLayer[5] will not be changed.
Please note that I do not want to make a new object while I want to replace the properties of one object with those of another object which makes it somehow different from other questions on Stackoverflow and I think it is not a duplication.
You need to clone the object, as otherwise you would just store the reference and in both fields and change them both. See this answers:
Creating a copy of an object in C#
How do you do a deep copy of an object in .NET (C# specifically)?
In that case you need to add a function to your NewLayerCounterMethod class, in which you copy all the properties of the other class to the new one. It would look somewhat like that then:
public void TakeProperties(NewLayerCounterMethod otherObject)
{
propA = otherObject.propA;
propB = otherObject.propB;
//And so on for all properties left
}
You could add guards so that you only update the properties if the new value is different to the old one, but I suggest to add those guards directly to the properties.
The above method is than called like that:
NewLayer[5].TakeProperties(NewLayer[7]);

A change in one object changes the second one too

I'm creating two objects and assign them with a data from IsolatedStorage.
But when I change one object the second one changes too. ( I think the problem may be the pointers are the same, but I can't solve it. )
private ArrayOfClsSimpleData lstUsers;
private ArrayOfClsSimpleData tmpLstUsers;
in class' globals
tmpLstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("users");
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("users");
The first status of the arrays:
Debug.Write(lstUsers.Count)
Output: 2
Debug.Write(tmpLstUsers.Count)
Output: 2
The counts are the same as expected. But, after I add an item to one list, the other list gets updated too and the counts are still same.
lstUsers.Add(new ArrayOfClsSimpleData());
Debug.Write(lstUsers.Count)
Output: 3
Debug.Write(tmpLstUsers.Count)
Output: 3
EDIT : IsolatedStorageHelper class is something to help to get objects, save object etc. that I do use for simplifying things, so just think it as getting objects from IsolatedStorage.
it is implemented like this:
public static T GetObject<T>(string key)
{
if (IsolatedStorageSettings.ApplicationSettings.Contains(key))
{
return (T)IsolatedStorageSettings.ApplicationSettings[key]; // return the object
}
return default(T); // if key doesn't exists , return default object
}
So it just gets it from IsolatedStorage.
If you don't know isolated storage you can see it from here
So, how can I fix the code so that I can change one without changing the other?
So, basically lstUsers and tmpLstUsers are references to the same object. All you have to do is to create a new one and copy content from the original. If you need a quick solution, then you can do it like this (code below). I just guess that ArrayOfClsSimpleData is some kind of array.
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("myKey");
tmpLstUsers = new ArrayOfClsSimpleData();
foreach (object user in lstUsers) // I don't know the type of objects in ArrayOfClsSimpleData, so I wrote 'object', but you should use the actual type
tmpLstUsers.Add(user);
The problem is that IsolatedStorage is just returning two pointers to the same data. So unless you copy the data, all changes will ultimately be to the same underlying data.
Think of it as two copies of your home address. Anything you change on your home affects all copies of your address since it is just an address and not the home itself.
What you will want to do is clone your object. Built in collections have clone or copy methods built in to do shallow copies, or if you built something yourself you will need to implement it yourself
The easiest way is to implement the IClonable interface and to use the clone method to achieve your copying.
https://msdn.microsoft.com/en-us/library/System.ICloneable.aspx
This basically involves going through and calling member wise clone for each complex object (which will copy all value types for you)
https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
I don't think cloning is necessary. Just create a new list instead of operating on the same instance. You can do that by calling ToList() on the returned instance:
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("myKey").ToList();
Can't you use the Clone() method of IClonable while fetching the object? looks like both list objects are getting same reference objects.

Get all writeable properties of an ADLDS-Class

I'm developing an application which can deal with a MS-ADLDS-Service.
Currently it is possible to create Directory-Entries and assign values to some properties.
Not a realy exciting task until this:
Im my application it's possible (it should be) to configure which properties of a class (for instance: the CN=Person class) should be assigned with values which are evaluated at runtime in my application.
Long story short:
I want to retrieve all (writeable) properties of a class. Without creating and saving a new CN=Person-Object before.
Currently i use my schemaBinding to get the Directory-classSchema-Entry of the Person-Class (CN=Person) from where i read some property-values (like "AllowedAttributesEffective", "mayContain", "AllowedAttributes") - i get the most properties by this way - but some Properties are missing! For instance the "telephoneNumber"-Property (attributeSchema: CN=Telephone-Number)
Does anybody know how to get these properties of a class? ADSI-Edit does this: when i create a new object with adsi-edit i can assign values to all possible properties before committing the new entry.
thanks a lot for any hint!
(.net code is welcome)
I have found the solution for my task!
Some of these properties are "calculated" and not persistent at the directoryentry.
So its meant to call the RefreshCache() Method and pass the needed property names as an string array.
directoryEntry.RefreshCache(new string[] { "allowedAttributesEffective",
"allowedAttributes",
"systemMayContain",
"systemMustContain" });
After that call, the properties have values....
if (directoryEntry.Properties["systemMayContain"]).Value != null)
{
/// Success
}

C# - Using a copy of Session-stored variables instead of reference

I have an asp:ImageButton with OnClick="Btn_OnClick".
In Btn_OnClick I have this line:
DataTable dtTable = (DataTable)Session["someSessionKey"]
and dtTable is altered in the function.
I've noticed that if the button's clicked more than once, the dtTable I take from the session contains the altered table, probably meaning dtTable is not a copy but a reference of the session variable.
How can I alter a copy of Session["someSessionKey"], and not the actual value?
Thanks!
DataTable dtTable = ((DataTable)Session["someSessionKey"]).Copy();
If the object in the Session implements ICloneable, you can use var myCopy = mySessionObject.Clone();. You would then have to read the documentation of the object to see what it exactly does.
This is because there is no generic solution to cloning. Mostly, objects have other non-scalar objects as properties, so it always depends on the scenario if you need to clone those child objects too.
When you author your own class, you can always call the protected MemberwiseClone() method that is defined in System.Object to get a flat clone. You can then choose if you want to add some additional cloning logic and if you want to make it available for callers outside.
If the object in the Session is a List<T> or an IEnumerable<T>, you can do var myCopiedList = new List<T>(myListInSession);. Keep in mind that the individual objects in that list are not cloned in that case. You'd have to foreach through them and clone each object manually. It's similar with the DataTable. You might need to manually create a new instance and copy the content over.
To manually clone an object that doesn't support any public method to do so, you'd have to create a new instance of it. Then you'd assign every property from the original object to the cloned object manually. That can be not only tedious, often it also won't work because there are protected members that you can't access easily.
Finally, you can resort to reflection or other tricks to try to clone an object. A quick google search gave me that result: C# Object clone wars.

Categories