Issue while invoking a class and storing data into it c# - c#

I have a class like this
public class basic
{
public bool Success { get; set; } = false;
public string Message { get; set; } = string.Empty;
}
public class ServiceResponse<T>:basic
{
public T? Data { get; set; }
}
public class ServiceResponse2<T> : basic
{
public T?[] Data { get; set; }
}
And I invoke it in my controller like this
ServiceResponse2<string> response = new ServiceResponse2<string>();
response.Success = true;
response.Message = "success";
response.Data[0] = filename;
response.Data[1] = outname;
when I do, I get runtime error in my lastline as: Object reference not set to an instance of an object. I hovered on top of Data variables and the values were null. Can I know what I'm missing here? Apologies if its a dumb doubt

The problem is that Data is an array, and this is never initialized to an object. You need to initialize it, for example:
response.Data = new string[]{filename, outname};
Or
public T?[] Data { get; set; } = new T[2];
However, I would be careful with using an array like this. What does Data means? How should it be used? Why can I change it however and whenever I want? How is it related to the other properties? Does a specific index have some special meaning? Does it promise to hold some specific number of items?
If this is intended to be used for requests to some type of service it is normal to use some form of serialization to convert objects to data. And this is normally done fairly close to the communication layer, so that most of the code can handle typed objects, and only a small part need to handle bits and bytes.

Related

Variables from a specific class equality both sides still changing together if one of the sides change

I am new to C# and WPF, and I am trying to define a new variable from a class and to give this new variable a value from an old variable and then make some changes to the new one. But the problem is that the new variable is still connected to the old variable and if I change anything in the new one, the changes will effect the old one:
MW.CurrentPreviewJob = addjob;
MW is another page than the page I am writing the code in,
and I define them as follows:
public static Job addjob;
public Job CurrentPreviewJob
{
get { return _currentPreviewJob; }
set {
_currentPreviewJob = value;
this.NotifyPropertyChanged("CurrentPreviewJob");
}
}
the class for the two variables is same and it is:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
}
So how can I take the value of CurrentPreviewJob without stay connecting to it?
This is because an object of a class is a reference type.
Let's take a look at an example:
We create an object of your class:
Job someJob = new Job();
What exactly is someJob? Well, when you create an instance of an object it is held in special area of memory, and someJob holds a reference to it (which is an address under which the program can find the instance in the memory).
So when you do something like:
Job someOtherJob = someJob;
you actually tell someOtherJob object to hold reference to the same address in a memmory as someJob object. that's how reference types work.
Now, if you do, for example:
someOtherJob.JOB_DESCRIPTION = "I changed that description in some other job object";
This is what happens: program checks the address which is referenced by somOtherJob object, goes there, finds the instance, and change its JOB_DESCRIPTION property's value. BUT remember that someJob objct (the "old" one) has a reference to the same instance in the memory - hnce, it will have the same, changed JOB_DESCRIPTION.
The most elegant thing to do here is to implement some kind of cloning method on the Job class.
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone() {
Job clone = new Job();
clone.JOB_ID = this.JOB_ID;
clone.JOB_DESCRIPTION = this.JOB_DESCRIPTION;
clone.TARGET_IMAGE = this.TARGET_IMAGE;
clone.JOB_USER = this.JOB_USER;
return clone;
}
}
and use it like:
Job someOtherJob = someJob.Clone();
That happens because both CurrentPreviewJob and addjob are reference types. They both reference the same object in the memory. So whatever you do to one variable will also affect the other, since they are pointing to the same object. You can make your Job have a Clone method like this:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone()
{
return new Job {
JOB_ID = this.JOB_ID,
JOB_DESCRIPTION = this.JOB_DESCRIPTION,
TARGET_IMAGE = this.TARGET_IMAGE,
JOB_USER = this.JOB_USER
};
}
}
Then you can assign your CurrentPreviewJob like this:
MW.CurrentPreviewJob = addjob.Clone();
This will make another object so your second variable is no longer linked to your previous.
Or another way is to make your class a struct
The problem is because Job is a class, and classes are reference types, meaning that if you assign one job variable to another, you just have too variables referencing the same data.
You could declare Job as a struct, which are value types and assignment would automatically create a copy.
I tend to avoid structs, simply because I don't like having to copy things around just to change properties, so I'd suggest adding an appropriate constructor to Job, like:
public Job(Job other) {
this.JOB_ID = other.JOB_ID;
this.JOB_DESCRIPTION = other.JOB_DESCRIPTION;
//...same for the other fields
}
Once you have the constructor, you can clone the object by doing:
var NewJob = new Job(OldJob);

protobuf-net: Handling nulls in IEnumerable? Via what attributes/settings?

Some sample code below. The interesting/problem case is the Data property in
Mad. This code blows up (null value in the enumerable). Also, it works if i don't use the static attributes but instead the runtime type model, where i put in member.SupportNull = true for the fields (which is the behaviour i want), so what am i missing in the attributes / settings? Google search seems to indicate this is an open issue with probuf-net? That the same functionality is not available via attributes?
As as aside, if someone could suggest a way - i really love the runtime type model, i want to use that everywhere with a nice compiled model... but with it i lose the object versioning that protocol buffers solves! (via explicit tags). Is there any good way to maintain object version compatibility (simply adding fields) without doing all the static notation with fixed tags?
Basically the key thing with the runtime model is the assignment of tag indices and i can't think of a way of handling versions without explicitly specifying the tag indices via attributes...
[ProtoContract]
[ProtoInclude(1, typeof(ing))]
public class Eff
{
[ProtoMember(2)]
public string gg { get; set; }
}
[ProtoContract]
public class ing : Eff
{
[ProtoMember(1)]
public int zz { get; set; }
}
[ProtoContract]
public class Mad
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public IEnumerable<ing> Data { get; set; }
[ProtoMember(3)]
public ing Single { get; set; }
}
private static void Main(string[] args)
{
var obj = new Mad
{
Name = "test"
,Data = new[] { new ing {gg = "ooga", zz = -101},null,new ing()}
,Single = new ing {gg = "abc", zz = -999}
};
var m = new MemoryStream();
Serializer.Serialize(m, obj);
m.Seek(0, SeekOrigin.Begin);
var copy = Serializer.Deserialize<Mad>(m);
}
Short answer, it seems unavailable via attributes.
Workaround i'm doing for now - for every single type of interest(including the whole inheritance hierarchy) - add it to the type model yourself (with default handling so that it processes attributes), then call .GetFields() and set .SupportNull = true for each field (or only the relevant one)

Generic Lists in a HttpSessionState stored in SQL

I'm working on a aspx application (C#), where I'm using HttpSessionState to save different objects in code behind between view changes. Some of these objects containts generic lists (List<T>), but those lists doesn't seem to be saved when I'm using an SQL database to store the state (sessionState mode = "SQLServer"). All other properties in the object gets saved, but when I try to retrieve the list, I get empty lists.
The funny thing is that it all works fine if I use sessionState mode = "InProc".
My classes have the Serializable attribute. I'm running C#/.NET 4.0.
Any ideas would be appreciated!
EDIT:
Just to clarify with some code (not verbatim!).
I have the classes I want to save (instances of) to my Session State:
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public List<MyOtherClass> Property3 { get; set; }
}
public class MyOtherClass
{
public string AnotherProperty1 { get; set; }
public string AnotherProperty2 { get; set; }
}
Then, in my Code Behind - one action saves objects of the previous classes:
public void MyMethod()
{
MyClass myClass = new MyClass()
{
Property1 = "One string",
Property2 = "One other string",
Property3 = new List<MyOtherClass>() { new MyOtherClass() { AnotherProperty1 = "One", AnotherProperty2 = "Ohter" } }
};
HttpContext.Current.Session["MyKey"] = myClass;
}
...and another action will retrieve that object:
public void MyOtherMethod()
{
MyClass myClass = (MyClass)HttpContext.Current.Session["MyKey"];
int c = myClass.Property3.Count; // Will be 0!!
}
So myClass.Property1 and myClass.Property2 will hold the strings I set previously, but myClass.Property3 is an empty list.
The problem you are describing could happen if you
Store a reference to an object in that generic list that is valid when you store it, but
the reference is no longer valid on subsequent requests.
An example would be storing a reference to a control from the Page.Controls collection - this reference would not be valid if you try to retrieve it on another postback. In fact, the reference may just be cleaned up by garbage collection (thus why your list appears to be empty).
Without seeing your actual code, it's tough to say for sure (although your example code does a great job of clarifying what you mean). But this seems likely to me.

When does an object's property become available?

Foreword: this is a long question and if you don't want to read and understand why I'm asking it then please spare the comment "why not simply test the code?"
I have an object model that looks somewhat like this:
public class MyObjectModel
{
public byte TypeOfNestedObject { get; set; }
public string NestedObjectInJson { get; set; }
public NestedObjectModel1 { get; set; }
public NestedObjectModel2 { get; set; }
public NestedObjectModel3 { get; set; }
public MyObjectModel()
{
NestedObjectModel1 = null;
NestedObjectModel2 = null;
NestedObjectModel3 = null;
}
public void DeserializeJsonString()
{
if (TypeOfNestedObject == 1) {
NestedObjectModel1 = "deserialize NestedObjectInJson
into NestedObjectModel1";
}
if (TypeOfNestedObject == 2) {
NestedObjectModel2 = "deserialize NestedObjectInJson
into NestedObjectModel2";
}
if (TypeOfNestedObject == 3) { NestedObjectModel3 ... }
}
}
Basically, the object is composed of three nested objects (NestedObjectModel1, NestedObjectModel2 and NestedObjectModel3). However, only one of them is actually used at any given time. In the database, I store fields that are used to recreate this object and one of the database fields is a json string that contains one of the three nested objects for a particular instance.
My query looks somewhat like this:
var TheObjectModel = from t in MyDC.Table
.....
select new MyObjectModel()
{
TypeOfNestedObject = t.TypeOfNestedObject,
NestedObjectInJson = t.NestedObjectInJson
};
I use the property TypeOfNestedObject to know which nested object the particular instance of MyObjectModel has. For the moment, after the the query has executed, I run a method that reads TypeOfNestedObject and deserializes the string NestedObjectInJson to the appropriate type and adds the deserialized object as the corresponding nested object.
Now I want to add a custom setter to NestedObjectInJson so that when this property is set when the query runs, the object automatically deserializes the string to the appropriate type. However, for this to work, the object would also have to have the property TypeOfNestedObject properly set. I want to write the setter like this:
public NestedObjectInJson
{
set {
if (this.TypeOfNestedObject == 1) {
NestedObjectModel1 = "deserialize NestedObjectInJson
into NestedObjectModel1 ";
}
}
}
If I write the setter like this, is the property TypeOfNestedObject needs to be available at the time the setter runs. If you notice, in the query, I load TypeOfNestedObject before I load NestedObjectInJson.
So the question is this: If I decide to remove the call to DeserializeJsonString and create this custom setter, will the property TypeOfNestedObject be available because in the query it's set before NestedObjectInJson or is the order in which the query is written make the availability of the property TypeOfNestedObject unpredictable?
This would work, the order is predictable.
However, I would advise against something like that. The clean approach would be to provide a constructor that takes the type and the JSON and performs the deserialization.
With that approach you would avoid the temporal coupling you currently have.

Non-trivial data binding

Trivial data binding examples are just that, trivial. I want to do something a little more complicated and am wondering if there's an easy, built in way to handle it.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
List<DataStruct> list = new List<DataStruct>()
{
new DataStruct(){Name = "Name 1", Value = "Value 1", ComplexValue = new ComplexValue(){Part1 = "1:P1", Part2 = "1:P2"}},
new DataStruct(){Name = "Name 2", Value = "Value 2", ComplexValue = new ComplexValue(){Part1 = "2:P1", Part2 = "2:P2"}}
};
listBox1.DataSource = list;
listBox1.DisplayMember = "ComplexValue.Part1";
}
}
public class DataStruct
{
public string Name { get; set; }
public string Value { get; set; }
public ComplexValue ComplexValue { get; set; }
}
public class ComplexValue
{
public string Part1 { get; set; }
public string Part2 { get; set; }
}
Is there an easy way to get the value of the Part1 property to be set as the display member for a list of DataStruct items? Above I tried something that I thought made sense, but it just defaults back to the ToString() on DataStruct. I can work around it if necessary, I was just wondering if there was something built into the data binding that would handle more complex data binding like above.
Edit: Using WinForms
perhaps not a built-in way, but you could always define
DataStruct {
public ComplexValuePart1 {
get { return ComplexValue.Part1; }
}
}
and set your DisplayMember to that
Personally I'd go for a simple solution like Jimmy's - however, if you want to do this (with regular win-form bindings), you'd need to use a custom type descriptor to flatten Part1 / Part2 as virtual properties of DataStruct. You can do this via ICustomTypeDescriptor or TypeDescriptionProvider. The latter is more involved, but cleaner from a "separation of concerns" viewpoint.
If you really want I can prepare an example (or there are many I've done in the past floating around) - but simple is beautiful: if you only have a few properties, a simple facade (i.e. pass-thru properties on DataStruct) would be preferable.

Categories

Resources