Below C# code
ResBlock resBlock1 = new ResBlock();
resBlock1.CustomerID = "ABC";
Block block = new Block();
block.Tag = resBlock1;
resBlock1 = null;
Console.WriteLine(((ResBlock)block.Tag).CustomerID);
The output would be "ABC". Of course this is the example of what I am facing but my code is way more complicated.
What I would like to understand is if there is a way to get block.Tag = null when the referenced object (resBlock1) is set to null or destroyed in some other way (which one?).
Classes are very simple as this is just an example:
public class ResBlock: IDisposable
{
public DateTime From { get; set; }
public DateTime To { get; set; }
public string CustomerID { get; set; }
public string ItemID { get; set; }
[...]
public ResBlock() {
DaysStatus = new List<ResBlockDayStatus>();
Deleted = false;
}
public bool LogicallyDeleted { get; set; }
public void Dispose() { }
}
public class Block
{
public bool Selected { get; set; }
public object Tag { get; set; }
public DateTime From { get; set; }
public DateTime To { get; set; }
}
No. You can't "destroy" an object in that way. That's just not the way that object lifetimes work in .NET. You could potentially change the Tag property to a WeakReference. That would prevent the Tag property from keeping the object within the WeakReference alive... but you still wouldn't be able to actively request object destruction.
Related
I'm working on a project where a record needs to be inserted, using a context class. However, before the insertion, one of the properties 'DataArea' is being set to a value that it should not have.
I started debugging the code to see where exactly this value is being set, and I have altered the short written version of the getter and setter (get; set;), to this:
public DataAreaEnum _DataArea;
public DataAreaEnum DataArea
{
get
{
return _DataArea;
}
set
{
_DataArea = value;
Debugger.Break();
}
}
By doing this, I had hoped that the debugger would break when the value was being set, however this is never hit. I am stuck and do not know how to think about this. Are there any other ways this value could have been set? How can I found out where this value was being set, if the breakpoint in the setter is never hit?
The complete class code:
using Works.Common.Models;
using System.Collections.Generic;
using System.Diagnostics;
namespace Works.Models.Toolsheets
{
public partial class Toolblad : ModelBase
{
public Toolblad()
{
Bijlagen = new HashSet<Bijlage>();
//Carrousels = new HashSet<Carrousel>();
KlauwplaatSlijpers = new HashSet<KlauwplaatSlijper>();
Klauwplaten = new HashSet<Klauwplaat>();
Laadtafels = new HashSet<Laadtafel>();
Laders = new HashSet<Lader>();
MblStangenLaders = new HashSet<MblStangenLader>();
MblStangenLaderWisselpunten = new HashSet<MblStangenLaderWisselpunt>();
Shuttles = new HashSet<Shuttle>();
Spankoppen = new HashSet<Spankop>();
SpankopSlijpers = new HashSet<SpankopSlijper>();
Revolvers = new HashSet<ToolbladRevolver>();
}
public DataAreaEnum _DataArea;
public DataAreaEnum DataArea
{
get
{
return _DataArea;
}
set
{
_DataArea = value;
Debugger.Break();
}
}
public bool IsTemplate { get; set; }
#region Navigation Properties
public virtual AlgemeneInfo AlgemeneInfo { get; set; }
public int AlgemeneInfoId { get; set; }
public ICollection<Bijlage> Bijlagen { get; set; }
//public ICollection<Carrousel> Carrousels { get; set; }
public ICollection<KlauwplaatSlijper> KlauwplaatSlijpers { get; set; }
public ICollection<Klauwplaat> Klauwplaten { get; set; }
public ICollection<Laadtafel> Laadtafels { get; set; }
public ICollection<Lader> Laders { get; set; }
public MachineGroep MachineGroep { get; set; }
public int MachineGroepId { get; set; }
public ICollection<MblStangenLader> MblStangenLaders { get; set; }
public ICollection<MblStangenLaderWisselpunt> MblStangenLaderWisselpunten { get; set; }
public ICollection<ToolbladRevolver> Revolvers { get; set; }
public ICollection<Shuttle> Shuttles { get; set; }
public ICollection<Spankop> Spankoppen { get; set; }
public ICollection<SpankopSlijper> SpankopSlijpers { get; set; }
#endregion Navigation Properties
}
}
I note that Toolblad is a partial class. Is there any code elsewhere changing _DataArea? Try renaming it to something else (e.g. _dataArea) just in that code file and see if it all still compiles.
Doing that will catch any unexpected code that tries to access it.
Whether you set the value of a Enum or not, it defaults to 0 which is why you are seeing a value for it without setting one.
First of all, please stick to how I accomplish this with the current setup, and not in trying to redesign how it is structured. I have to build an app/web service to receive a JSON query. The JSON is generated by a widget that we can not customize. I used Visual Studio to create the class structure from a JSON example.
I want to test my service, and I'm getting errors in SOAPUI, so I need something where I can debug, so I'm hard-coding the JSON input object for my Service Reference.
Here are the classes, as they reside on the web service -
[DataContract]
public class QuoterIn
{
[DataMember]
public Quoterinput quoterinput { get; set; }
}
public class Quoterinput
{
public string agent_id { get; set; }
public string key { get; set; }
public string auto_assign { get; set; }
public Consumer consumer { get; set; }
public string viaEmail { get; set; }
}
public class Consumer
{
public string brand_id { get; set; }
public string full_name { get; set; }
public Addresses_Attributes[] addresses_attributes { get; set; }
public string birth_or_trust_date { get; set; }
public string gender { get; set; }
public Emails_Attributes[] emails_attributes { get; set; }
public Phones_Attributes[] phones_attributes { get; set; }
public Cases_Attributes[] cases_attributes { get; set; }
}
public class Addresses_Attributes
{
public string zip { get; set; }
}
public class Emails_Attributes
{
public string value { get; set; }
}
public class Phones_Attributes
{
public string value { get; set; }
}
public class Cases_Attributes
{
public Quoting_Details_Attributes[] quoting_details_attributes { get; set; }
}
public class Quoting_Details_Attributes
{
public string carrier_id { get; set; }
public string duration_id { get; set; }
public string policy_type_id { get; set; }
public string plan_name { get; set; }
public string product_type_name { get; set; }
public string face_amount { get; set; }
public string carrier_health_class { get; set; }
public string planned_modal_premium { get; set; }
public string premium_mode_id { get; set; }
public string health_class_id { get; set; }
}
Looking at the sub-class of Consumer, there are several sub-classes that are arrays - address_attributes, phone_attributes, and email_attributes.
I'm able to initialize the main JSON input/inquiry container, and then I can initialize the main class and the sub-class of "Consumer." I can enter data for the main fields, and then fields in the sub-class of Consumer, but I can't initialize the arrays.
Here's the code up until this point for populating that input container -
protected void btnRun_Click(object sender, EventArgs e)
{
QuoterIn req = new QuoterIn();
req.quoterinput = new Quoterinput();
req.quoterinput.consumer = new Consumer();
req.quoterinput.agent_id = "1938";
req.quoterinput.key = "afasdfasdfasdfasdfasd";
req.quoterinput.auto_assign="true";
req.quoterinput.consumer.brand_id = "21264";
req.quoterinput.consumer.full_name = "Fred Smith";
req.quoterinput.consumer.addresses_attributes[0].zip = "53704";
.................(more code like this, but this last line is where the program fails)
Since we aren't going to take in multiple email addresses or phone numbers, I'd be fine with not having it be an array, but I'm worried that the incoming JSON with all the grouping and bracketing will fail if it's not set up like an array. I've tried to initialize instance zero like this -
req.quoterinput.consumer.addresses_attributes[0] = new Addresses_Attributes();
.... and Visual Studio likes the code syntax-wise, but it doesn't initialize an instance when it runs, and then I get the "Object reference not set to an instance of an object." error when it runs. It hasn't allowed me to initialize the array using more generic methods since it has to map to this specific property we've already declared.
I have no doubt it's probably straightforward, but I'm not all that experienced in manipulating arrays and lists like this, and I haven't been able to find examples of arrays of sub-classes within subclasses of properties.
Just instantiate / assign the address at the same time. Something like this should work:
req.quoterinput.consumer.addresses_attributes = new []
{
new Addresses_Attributes
{
zip = "53704"
}
};
Another way (since the property toy are trying to set is an Array), is to create a dynamic sized list, add to it, then convert it back during declaration.
var addresses = new List<Addresses_Attributes>
{
new Addresses_Attributes {zip = "53704"}
};
req.quoterinput.consumer.addresses_attributes = addresses.ToArray();
Or, you can assign it an array of size 1, and then set it up from there:
req.quoterinput.consumer.addresses_attributes = new Addresses_Attributes[1];
req.quoterinput.consumer.addresses_attributes[0] = new Addresses_Attributes { zip = "666" };
This question already has answers here:
copy chosen properties to object of other type
(2 answers)
How to cast between 2 types of the same name and internal sturcture but from different assemblies?
(5 answers)
Copy two identical object with different namespaces (recursive reflection)
(7 answers)
Closed 2 years ago.
I'm trying to find the best way to populate my constructor with another constructor that have almost the same structure without setting each attribute,
So i have constructor Altridatiidentificativi in ModelRA constructor:
public class Altridatiidentificativi
{
public string denominazione { get; set; }
public string indirizzo { get; set; }
public string numeroCivico { get; set; }
public string cap { get; set; }
public string comune { get; set; }
public string provincia { get; set; }
public string nazione { get; set; }
public bool modificati { get; set; }
public string defAliquotaIVA { get; set; }
public bool nuovoUtente { get; set; }
}
And Altridatiidentificativi in Documenti:
public class Altridatiidentificativi
{
public bool nuovoUtente { get; set; }
public string denominazione { get; set; }
public string indirizzo { get; set; }
public string numeroCivico { get; set; }
public string cap { get; set; }
public string comune { get; set; }
public string provincia { get; set; }
public string nazione { get; set; }
}
As you can see the structure is almost the same, just constructor in ModelRA has this two extras modificati and defAliquotaIVA
So i was wondering if it's possible in some way to pass inside ModelRA.Altridatiidentificativi the Documenti.Altridatiidentificativi and then add the value to the extras
I was trying to do something like this :
public ModelRA initializeRA(Documento documento)
{
ModelRA model = new ModelRA();
model.altriDatiIdentificativi = <Altridatiidentificativi>(documento.altriDatiIdentificativi);
model.altriDatiIdentificativi.defAliquotaIVA = "";
model.altriDatiIdentificativi.modificati = false;
return model;
}
but i get error in <Altridatiidentificativi> "it's a type not a valid constructor in specific context"
Is there a way to reach what i'm trying to do or i have to set all the attributes manually?
Usually this pattern is a signal that there's a concept in your business model that needs to be abstracted into a composable pattern. The ModelRA.Altridatiidentificativi class could look like:
public class Altridatiidentificativi
{
public ModelRA.Altridatiidentificativi ModelRAAltridatiidentificativi { get; set; }
public bool modificati { get; set; }
public string defAliquotaIVA { get; set; }
}
Then your initialization code could look like this:
public ModelRA initializeRA(Documento documento)
{
ModelRA model = new ModelRA();
model.altriDatiIdentificativi.ModelRAAltridatiidentificativi = documento;
model.altriDatiIdentificativi.defAliquotaIVA = "";
model.altriDatiIdentificativi.modificati = false;
return model;
}
Tangentially I should mention that it's usually good practice to use property initializers and constructors unless you have a specific reason that you need initialization methods.
public class Altridatiidentificativi
{
public string ModelRA.Altridatiidentificativi ModelRAAltridatiidentificativi { get; set; }
public bool modificati { get; set; } = false; // unnecessary: this is default.
public string defAliquotaIVA { get; set; } = "";
public Altridatiidentificativi(ModelRA.Altridatiidentificativi modelRAAltridatiidentificativi)
{
this.modelRAAltridatiidentificativi = ModelRAAltridatiidentificativi;
}
}
In my web application, I want to notify user when certain things are changed through UI. For example my Project class looks like this
public class Project
{
public string Name { get; set; }
public TaskStatus Status { get; set; }
public string Planner { get; set; }
public DateTime ScheduleStart { get; set; }
public DateTime ScheduleEnd { get; set; }
public double EstimatedCost { get; set; }
public double ActualCost { get; set; }
public string AssignedTo { get; set; }
}
Now I have this information shown up on UI and a particular user having rights to change certain things (e.g. Status, schedule, cost etc.) can change this information. So what I want is that when something is changed by a user, then Emails should be sent to notify Project Manager lets say or anyone interested.
I have all other required code written to send emails and manage rights etc. Now I want to specifically see exactly what things changed for example If only Planner changed, or status changed then email should contain new and old value like TFS generates notifications.
P.S: Above code shows a very simple version of my Project class, actual class has more than 30 attributes. So I was thinking that instead of making comparison of each individual property there should be an easier and generic way that tells me which properties have changed, so that I can notify based on them.
A simple solution based on reflection. Note that it could be optimized, and it doesn't support (at this time) comparing inner collections/objects. The compared object must be POD (Plain Old Data)
public class Project
{
public string Name { get; set; }
public TaskStatus Status { get; set; }
public string Planner { get; set; }
public DateTime ScheduleStart { get; set; }
public DateTime ScheduleEnd { get; set; }
public double EstimatedCost { get; set; }
public double ActualCost { get; set; }
public string AssignedTo { get; set; }
public Project Clone()
{
// If your object has inner collections, or
// references to other objects, you'll have to deep
// clone them ***manually***!!!
return (Project)MemberwiseClone();
}
}
public static class SimpleComparer
{
// Item1: property name, Item2 current, Item3 original
public static List<Tuple<string, object, object>> Differences<T>(T current, T original)
{
var diffs = new List<Tuple<string, object, object>>();
MethodInfo areEqualMethod = typeof(SimpleComparer).GetMethod("AreEqual", BindingFlags.Static | BindingFlags.NonPublic);
foreach (PropertyInfo prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
object x = prop.GetValue(current);
object y = prop.GetValue(original);
bool areEqual = (bool)areEqualMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { x, y });
if (!areEqual)
{
diffs.Add(Tuple.Create(prop.Name, x, y));
}
}
return diffs;
}
private static bool AreEqual<T>(T x, T y)
{
return EqualityComparer<T>.Default.Equals(x, y);
}
}
Now, you'll need a Clone() method:
public class Project
{
public string Name { get; set; }
public TaskStatus Status { get; set; }
public string Planner { get; set; }
public DateTime ScheduleStart { get; set; }
public DateTime ScheduleEnd { get; set; }
public double EstimatedCost { get; set; }
public double ActualCost { get; set; }
public string AssignedTo { get; set; }
public Project Clone()
{
// If your object has inner collections, you'll have to deep
// clone them ***manually***!!!
return (Project)MemberwiseClone();
}
}
and then...
var current = new Project();
var original = current.Clone();
current.ActualCost = 10000;
var diffs = SimpleComparer.Differences(current, original);
foreach (var diff in diffs)
{
Console.WriteLine("'{0}' changed from {1} to {2}", diff.Item1, diff.Item3, diff.Item2);
}
I'm assuming that you are referring to property values and not the actual class' properties. To be able to compare which property values have changed, there has to be two versions of the object, say old and updated. I would suggest implementing the IEquatable interface, this comes handy if you have complex objects which in your case a nested class TaskStatus which also have properties of its own that you need to compare. You can also let TaskStatus or other nested classes implement the IEquatable interface such that you don't have to worry about comparing their property values giving you the advantage of just doing a single call to Project's Equals() method. You can have the logic for getting the changes inside the overriden Equals() method.
If you don't want to hardcode each property for comparison, a little reflection would do. :)
public class Project : IEquatable<Project>
{
public string Name { get; set; }
public TaskStatus Status { get; set; }
public string Planner { get; set; }
public DateTime ScheduleStart { get; set; }
public DateTime ScheduleEnd { get; set; }
public double EstimatedCost { get; set; }
public double ActualCost { get; set; }
public string AssignedTo { get; set; }
public bool Equals(Project other)
{
bool flag = true;
if (this.Name != other.Name)
//--Do something
flag = false;
//TaskStatus otherTaskStatus = other.Status;
//flag = other.Status.Equals(otherTaskStatus);//compare nested classes here
return flag;
}
}
public class TaskStatus : IEquatable<TaskStatus>
{
public bool Equals(TaskStatus other)
{
throw new NotImplementedException();
}
}
You can use a class as follows which will store the old and new values of a property each time the property is changed even after updating it on the UI and then the object can be used to retrieve both the values. All you need to do is to create an instance of this class under set method of each property. You can also check whether the value is changed or not before creating the object.
public class PropertyChangingEventArgs : EventArgs
{
public PropertyChangingEventArgs()
{
}
public PropertyChangingEventArgs(string propName, object oldValue, object newValue)
{
PropertyName = propName;
OldValue = oldValue;
NewValue = newValue;
}
public string PropertyName { get; set; }
public object OldValue { get; set; }
public object NewValue { get; set; }
}
On property side, you can do this:
private string family;
public string Family
{
get { return family; }
set
{
if (family != value)
{
PropertyChangingEventArgs e = new PropertyChangingEventArgs("Family", family, value);
OnPropertyChanging(e);
family = value;
OnPropertyChanged("Family");
}
}
}
After updating, you can check which all properties have changed (or you can keep populating a list of changed properties each time a property is changed) and mail the list with old and new values.
Take a look at PropertyChangedEventHandler. I think it should do the trick if I am understanding your question correctly.
https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
I have the following example schema:
public class CounterReading
{
public int CounterReadingId { get; set; }
public virtual Counter Counter { get; set; }
public DateTime Date { get; set; }
public decimal Reading { get; set; }
public CounterReading()
{
Date = DateTime.Now;
}
}
public class Counter
{
[Key, ForeignKey("Meter")]
public int CounterId { get; set; }
public virtual Meter Meter { get; set; }
public virtual ObservableCollection<CounterReading> Readings { get; set; }
[NotMapped]
public CounterReading CurrentReading
{
get
{
if(Readings.Count > 0)
{
return Readings.MaxBy(m => m.Reading);
}
return null;
}
}
}
public abstract class Meter
{
public int MeterId { get; set; }
public string EANNumber { get; set; }
public string MeterNumber { get; set; }
public virtual Premise Premise { get; set; }
}
public class WaterMeter : Meter
{
public virtual Counter Counter { get; set; }
public WaterMeter()
{
Counter = new Counter();
Counter.Readings = new ObservableCollection<CounterReading>();
}
}
And what doesn't work is that my WaterMeter does not have any CounterReadings when I load it from database. This is because I set my Counter in my constructor, to avoid NullReferencesExceptions when I create a new WaterMeter in runtime.
If I remove my WaterMeterconstructor, EF loads my readings just fine. But that means I have loads of NullReferences when using my application without reloading my data each and every time.
What's the best way to solve this?
Edit:
NRE:
Well firstly, there is a disjoint in the code you have in your question and the actual code you are executing (as per the image you added) which is why I couldn't see a problem.
However, from the image you posted it's clear that the problem is the fact that you have Readings as a private field - EF CodeFirst requires navigation properties to be marked as public virtual in order for them to be initialised.
To avoid null reference exception with collection, you should introduce local readonly collection field and initialize it empty collection.
public class Counter
{
private readonly ObservableCollection<CounterReading> readings = new ObservableCollection<CounterReading>();
public virtual ObservableCollection<CounterReading> Readings
{
get { return readings; }
set { readings = value; }
}
[Key, ForeignKey("Meter")]
public int CounterId { get; set; }
public virtual Meter Meter { get; set; }
[NotMapped]
public CounterReading CurrentReading
{
get
{
return Readings.MaxBy(m => m.Reading);
}
}
}
I've got one addition to Evgeny's answer. Instead of always creating a new instance of the collection , you can make it conditionally so it only creates a new instance when this property is actually called:
private readonly ObservableCollection<CounterReading> readings;
public virtual ObservableCollection<CounterReading> Readings
{
get
{
if(_readings == null)
{
_readings = new ObservableCollection<CounterReading>();
}
return readings;
}
set { readings = value; }
}
If you don't need to add logic to the getter and setter, why don't you consider using this:
public virtual ObservableCollection<CounterReading> Readings {get;set;}