Reflection : Object reference not set to an instance of an object - c#

I try to call a method using reflection.
My object :
public class CurrentSearch
{
public string currentUniverse { get; set; }
public string currentApplication;
public string currentUsage;
...
My code :
CurrentSearch cS = SessionUtils.getCS();
cS.currentUniverse = "lol";
string methodName = "currentUniverse" ;
var test = typeof(CurrentSearch).GetMethod(methodName).Invoke(cS, null);
But i get the error "Object reference not set to an instance of an object." on the last line. I've checked cS, it's not null...
What's wrong?
Thx

currentUniverse is a property, so you need to use GetProperty, not GetMethod.
void Main()
{
CurrentSearch cs = new CurrentSearch();
cs.currentUniverse = "lol";
string methodName = "currentUniverse" ;
Console.WriteLine(typeof(CurrentSearch).GetProperty(methodName).GetValue(cs));
^^^^^^^^^^^
}
public class CurrentSearch
{
public string currentUniverse { get; set; }
public string currentApplication;
public string currentUsage;
}

Related

C# Nested Properties initialize

I have the below simple declaration of nested properties (simplified):
public class standardMessage
{
public messageProperties message { get; set; }
public messageFlags flag { get; set; }
}
public class messageProperties
{
public string messageSubject { get; set; }
public string messageBody { get; set; }
}
public class messageFlags
{
public Boolean flagImportant { get; set; }
public Boolean flagPersonal { get; set; }
}
Upon initialization, I am trying to enter values, but seems I am missing something:
public class Program
{
static void Main(string[] args)
{
standardMessage myMessage = new standardMessage();
messageProperties myMsgProperties = new messageProperties();
myMsgProperties.messageSubject = "Hey!";
myMsgProperties.messageBody = "Howdy";
//below code throws error System.NullReferenceException: 'Object reference not set to an instance of an object.'
//MyMessage.message.messageSubject = "Greetings";
//MyMessage.message.messageBody = "Happy weekend";
//error - how do I print the values?
Console.WriteLine(myMessage.message.messageSubject.ToString());
Console.ReadLine();
}
}
Could you please help me with the above? wither way I tried, it doesn't run
You should initialize the instance of messageProperties first, before accessing the instance properties
myMessage.message = new messageProperties
{
messageBody = "Happy weekend",
messageSubject = "Greetings"
};
instead of this
//below code throws error System.NullReferenceException: 'Object reference not set to an instance of an object.'
//MyMessage.message.messageSubject = "Greetings";
//MyMessage.message.messageBody = "Happy weekend";
Then you'll be able to print it out successfully
Console.WriteLine(myMessage.message.messageSubject);
prints
Greetings
Another option is to initialize nested properties in constructor, like that
public class standardMessage
{
public standardMessage()
{
message = new messageProperties();
flag = new messageFlags();
}
public messageProperties message { get; set; }
public messageFlags flag { get; set; }
}
Then you can assign the values like you want
myMessage.message.messageSubject = "Greetings";
myMessage.message.messageBody = "Happy weekend";
Or you can finish you snippet and set the nested property directly
standardMessage myMessage = new standardMessage();
messageProperties myMsgProperties = new messageProperties();
myMsgProperties.messageSubject = "Hey!";
myMsgProperties.messageBody = "Howdy";
myMessage.message = myMsgProperties;
Console.WriteLine(myMessage.message?.messageSubject);
Prints
Hey!
Null-conditional operator ? will help you to avoid NullReferenceException if any
You need to modify the definition for your standardMessage class to either use inline initializers or add a default constructor (whichever works depending upon the language version you are using).
public class standardMessage
{
public standardMessage()
{
message = new messageProperties();
flag = new messageFlags();
}
public messageProperties message { get; set; } = new messageProperties();
public messageFlags flag { get; set; } = new messageFlags();
}

Winforms combobox displaying class names instead of actual object name

I have this class that contains a static list
public class TypeList
{
public string Name;
public string NameTag;
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
public static List<TypeList> DataType = new List<TypeList>() {
new TypeList("DataType","-1"),
new TypeList("OpOne","1"),
new TypeList("OpTwo","2"),
};
}
I then put the static list called DataType into a combobox:
public void RefreshList()
{
List<TypeList> data = new List<TypeList>();
data = TypeList.DataType;
typeCB.DataSource = data;
typeCB.DisplayMember = "Name";
typeCB.ValueMember = "NameTag";
typeCB.SelectedValue = -1;
typeCB.SelectedText = "Select DataType";
}
However, when I run it, all I get are the classnames in my combobox. Is something wrong with my code? I tried to do
data.Select(x=>x.Name).ToList()
But that just gives me the name portion.
I might be wrong, but based on the Documentation and Example it might be that this Feature only works with public property getters, not public fields:
Gets or sets the property to display for this ListControl.
public class USState
{
private string myShortName;
private string myLongName;
public USState(string strLongName, string strShortName)
{
this.myShortName = strShortName;
this.myLongName = strLongName;
}
public string ShortName
{
get
{
return myShortName;
}
}
public string LongName
{
get
{
return myLongName;
}
}
}
Of course I would also advise against making the list a part of the Type class. A simple Programm scope static would be better. If that is the case and as autoproties have have become a thing by now, this should be enough of a fix:
public class Type
{
public string Name { private set; get } ;
public string NameTag {private set; get };
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
}
//use in the class of main, the form or some similar central point
static List<Type> TypeList = new List<Type>();

Using a variable to access object member value

I'm trying to access member values of the following class:
public class EditorialDateFormat
{
public string en; <------ TRYING TO GET ITS VALUE
public string fr; <------ OR THIS VALUE
public string Default;<-- OR THIS ONE
}
public class Params
{
public string Template;
public string MainTagID;
public string[] NavigationFilters;
public EditorialDateFormat EditorialDateFormat;
}
public class Site
{
public string Name;
public string CreationFolder;
public Params Params;
public string[] Feed;
public string Endpoint;
public string[] TargetDatabases;
}
I could do it easily like :
site.Params.EditorialDateFormat.en(for example) but "en" string is actually saved in a variable.
I tried the following code :
// Myvariable contains "en"
object c = GetPropValue(site.Params.EditorialDateFormat, MyVariable);
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetMember(propName);
}
But it returns me a MemberInfo object without the member value
I would appreciate some help!
Thanks in advance
You want to read field (public instance field's value), that's why we put GetField:
//TODO: rename the method: it doesn't read property (Prop)
public static object GetPropValue(object src, string propName) {
return src
.GetType()
.GetField(propName, BindingFlags.Public | BindingFlags.Instance)
.GetValue(src);
}
public class EditorialDateFormat
{
private string _en;
public string en
{
get { return !string.IsNullOrEmpty(_en) ? _en : fr; }
set { _en = value; }
}
private string _fr;
public string fr
{
get { return !string.IsNullOrEmpty(_fr) ? fr : Default; }
set { _en = value; }
}
public string Default { get; set; }
}
and you can use it like var c=site.Params.EditorialDateFormat.en
in elegant way

C# json deserialize to (this) inside object

I am trying to get an object to deserialize into itself. I have tride the following:-
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
}
public void load(string fname)
{
string s = File.ReadAllText(fname);
this = JsonConvert.DeserializeObject<JobID>(s);
}
But the word this is 'read only' according to the error I get.
I have used 'this.jobname = "X";' before so clearly 'this' is not read only.
I am using Newtonsof.Json.
Why not use static method to load the object. Such as :
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public static JobId Load(string fname){
string s = File.ReadAllText(fname);
return JsonConvert.DeserializeObject<JobID>(s);
}
}
Although you can assign a value to a property of 'this', you can't change the object to which 'this' refers to.
The 'this' keyword refers to the current object instance in the context (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/this).
Assuming the Load function is inside another object (or static), you could do something like:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
}
public class JobReader
{
// Property to store deserialized object
public JobID Job { get; set; }
public void load(string fname)
{
string s = File.ReadAllText(fname);
// Assign object to property.
this.JobID = JsonConvert.DeserializeObject<JobID>(s);
}
}
You can use the static method as suggested by Xbotter to create a new instance. But for some reason if you want to deserialize the file content into current object only, then easiest way would be:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public void load(string fname)
{
string s = File.ReadAllText(fname);
JobID tmp = JsonConvert.DeserializeObject<JobID>(s);
copy(tmp);
}
public void copy(JobID tmp)
{
this.jobname = tmp.jobname;
// do the same for other properties that you want to copy
}
}
If you want to do this without a static method, you can use the JsonSerializer.Populate method. Example code:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public void load(string fname)
{
string s = File.ReadAllText(fname);
new JsonSerializer().Populate(new JsonTextReader(new StringReader(s)), this);
}
}
Anssssss provided the answer I've been looking for years. Thank you!
This is how I used it:
bool bOk = false;
StreamReader myFileStream = null;
Newtonsoft.Json.JsonSerializer mySerializer = new Newtonsoft.Json.JsonSerializer();
try
{
myFileStream = File.OpenText(sFilePath);
mySerializer.Populate(myFileStream, this);
bOk = true;
}
catch (Exception e)
{
string sException = e.ToString();
CHelper.ThrowException(new Exception(sException + "\n\n" + sFilePath));
}
finally
{
if (myFileStream != null)
{
myFileStream.Close();
}
}
return bOk;

C# Accessing custom attribute of owner object

How can I access the custom attribute of the parent or owner object.
Look at the FieldInfo property of the SQLFieldInfo struct
Here's a more detailed program that will compile and run that shows what I need.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Employee myclass = new Employee();
// Load from sql server...
myclass.Name = "Alain";
myclass.Age = 51;
//----
MessageBox.Show(myclass.Name.ToString()); // Should return Alain
MessageBox.Show(myclass.Age.FieldInfo.Type.ToString()); // Should output "int"
}
}
// This next class is generated by a helper exe that reads SQL table design and create the class from it
[SQLTableAttribute(DatabaseName = "Employees", Schema = "dbo", TableName = "Employees")]
public class Employee
{
[SQLFieldAttribute(FieldName = "ID", Type = SqlDbType.Int)]
public SQLFieldInfo<int> ID { get; set; }
[SQLFieldAttribute(FieldName = "Name", Type = SqlDbType.NVarChar, Size = 200)]
public SQLFieldInfo<String> Name { get; set; }
[SQLFieldAttribute(FieldName = "Age", Type = SqlDbType.Int)]
public SQLFieldInfo<int> Age { get; set; }
}
public struct SQLFieldInfo<T>
{
private readonly T value;
public SQLFieldInfo(T Value)
{
this.value = Value;
}
public static implicit operator SQLFieldInfo<T>(T Value)
{
return new SQLFieldInfo<T>(Value);
}
public T Value
{
get
{
return this.value;
}
}
public override string ToString()
{
return this.value.ToString();
}
public SQLFieldAttribute FieldInfo
{
get
{
// Need to retreive the attribute class of the parent or declaring member
return null;
}
}
}
// Holds the sql field information
public class SQLFieldAttribute : Attribute
{
public string FieldName { get; set; }
public SqlDbType Type { get; set; }
public bool AllowNull { get; set; }
public int Size { get; set; }
}
// Holds the sql table information
public class SQLTableAttribute : Attribute
{
public string DatabaseName { get; set; }
public string Schema { get; set; } = "dbo";
public string TableName { get; set; }
}
Thank you!
Alain
My data class is as follows (should be fairly translatable to A above):
public class Foo
{
[Argument(Help = "Name", AssignmentDelimiter = "=")]
public string Name
{
get;
set;
}
}
A helper class is responsible of reading attribute values of objects:
static public string GetCommandLineDelimiter<T>(Expression<Func<T>> property)
{
if(property != null)
{
var memberExpression = (MemberExpression)property.Body;
string propertyName = memberExpression.Member.Name;
PropertyInfo prop = typeof(Arguments).GetProperty(propertyName);
if(prop != null)
{
object[] dbFieldAtts = prop.GetCustomAttributes(typeof(ArgumentAttribute), true);
if(dbFieldAtts.Length > 0)
{
return ((ArgumentAttribute)dbFieldAtts[0]).AssignmentDelimiter;
}
}
}
return null;
}
To use it, simply:
string delimiter = GetCommandLineDelimiter(() => myObject.Name);
That will get the attribute value of AssignmentDelimiter on property Name, i.e. "=".
First, MSDN is your friend.
Then, if you want to get the attributes for ancestors just specify true in the inherit flag of the method:
var attribute = typeof(A).GetProperty("myprop").GetCustomAttributes(true)
.OfType<MycustomAttrib>().FirstOrDefault();
This works. I am doing a lazy initialization of a reference to the custom attribute by using reflection to look at all the properties of all the types.
public class MycustomAttribAttribute : Attribute
{
public MycustomAttribAttribute(string name)
{
this.Name=name;
}
public string Name { get; private set; }
}
class A
{
public A() { MyProp=new B(); }
[MycustomAttrib(name: "OK")]
public B MyProp { get; set; }
}
class B
{
private static Lazy<MycustomAttribAttribute> att = new Lazy<MycustomAttribAttribute>(() =>
{
var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes;
foreach(var item in types)
{
foreach(var prop in item.DeclaredProperties)
{
var attr = prop.GetCustomAttributes(typeof(MycustomAttribAttribute), false);
if(attr.Length>0)
{
return attr[0] as MycustomAttribAttribute;
}
}
}
return null;
});
public string MyProp2
{
get
{
return att.Value.Name;
}
}
}
class Program
{
static void Main(string[] args)
{
// Finds the attribute reference and returns "OK"
string name = (new A()).MyProp.MyProp2;
// Uses the stored attribute reference to return "OK"
string name2 = (new A()).MyProp.MyProp2;
}
}

Categories