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
Related
So, I've created a cmdlet with a dynamic parameter:
public class MyCmdLet : IDynamicParameters
{
public string StandbyFilePath => _standbyFilePathDynamicParameter.StandbyFilePath;
private StandbyFilePathDynamicParameter _standbyFilePathDynamicParameter;
public object GetDynamicParameters()
{
if (RecoveryState == RestoreMode.StandBy)
{
return _standbyFilePathDynamicParameter = new StandbyFilePathDynamicParameter();
}
return null;
}
}
public class StandbyFilePathDynamicParameter
{
[Parameter(Mandatory = true)]
public string StandbyFilePath
{
get { return _standbyFilePath; }
set { _standbyFilePath = value; }
}
private string _standbyFilePath;
}
So everything is great except, this parameter is not shown in cmdlet help. Is there anyway how to add help ?
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;
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;
}
I am serializing with xml, and I had it working with just a simple class, but when I made a secondary class, of which the simple class was just a component, the serialization stopped working. It fails with an "Error reflecting type" error at the serialization stage. The code is as follows:
public class CustomField
{
[XmlAttribute("FieldID")]
public string FieldID;
[XmlAttribute("FieldValue")]
public string FieldValue;
public CustomField() { }
public CustomField(string fieldID, string fieldValue)
{
this.FieldID = fieldID;
this.FieldValue = fieldValue;
}
}
[XmlType("Entry")]
public class CustomEntry
{
[XmlAttribute("Author")]
public string Author;
[XmlAttribute("Title")]
public string Title;
[XmlAttribute("Trial")]
public string Trial;
[XmlAttribute("Responses")]
public List<CustomField> Responses;
public CustomEntry() { }
}
public static class EntrySerializer
{
public static void SerializeObject(this CustomEntry entry, string file)
{
var serializer = new XmlSerializer(typeof(CustomEntry));
using (var stream = File.OpenWrite(file))
{
serializer.Serialize(stream, entry);
}
}
}
Is it a labeling issue with the Xml markers, or is it something else?
Try defining your serializer like this:
var serializer = new XmlSerializer(typeof(CustomEntry), new Type[] { typeof(CustomField) });
You need to inform the serializer of the additional types it is expecting to serialize.
I usually tag with XMLRoot (two places). I need to see sample of XML to give better answer.
[XmlRoot("CustomField")]
public class CustomField
{
[XmlAttribute("FieldID")]
public string FieldID;
[XmlAttribute("FieldValue")]
public string FieldValue;
public CustomField() { }
public CustomField(string fieldID, string fieldValue)
{
this.FieldID = fieldID;
this.FieldValue = fieldValue;
}
}
[XmlRoot("Entry")]
public class CustomEntry
{
[XmlAttribute("Author")]
public string Author;
[XmlAttribute("Title")]
public string Title;
[XmlAttribute("Trial")]
public string Trial;
[XmlAttribute("Responses")]
public List<CustomField> Responses;
public CustomEntry() { }
}
I've been searching for a while now and tested several methods, but i didn't find the answer i was looking for. I'll try to explain.
I have an object with several fields/properties. These properties have custom attributes.
What i want is to get the custom attribute from a specific propertie without all the knowlege of the object.
The are the base classes
// FieldAttr has a public Text propery
public class TestObject
{
// Declare fields
[FieldAttr("prop_testfld1")]
public FLDtype1 testfld1 = new FLDtype1();
[FieldAttr("prop_testfld2")]
public FLDtype2 testfld2 = new FLDtype2();
[FieldAttr("prop_testfld3")]
public FLDtype1 testfld3;
}
public class FLDtype1
{
public string Value { get; set; }
}
public class FLDtype2
{
public Guid Value { get; set; }
}
public sealed class FieldAttr: System.Attribute
{
private string _txt;
public EntityFieldType(string txt)
{
this._text = txt;
}
public string Text { get { return this._text; } }
}
And i want to be able to do this in my application:
static void Main(string[] args)
{
TestObject test = new TestObject();
// (Option 1: preferred)
Console.WriteLine(test.testfld1.getFieldAttr().Text);
// (Option 2)
Console.WriteLine(test.getFieldAttr(test.testfld1).Text);
}
Is this possible? I've seen methods to get custom attribute values from all properties/fields of an object, but not for a specific field.
I've got a working method to get custom attribute from an enum, but wasn't able to recreate it for object fields/properties. This is because i couldn't get the name of the field i was trying to explore, because (for example) test.testfld1.ToString() give's me "ns.FLDtype1".
Looking forward for the answer :)
(and excuse my english)
Yes it is possible:
public static class Extensions
{
public static FieldAttr GetFieldAttr(
this TestObject source,
Expression<Func<TestObject,object>> field)
{
var member = field.Body as MemberExpression;
if (member == null) return null; // or throw exception
var fieldName = member.Member.Name;
var test = typeof (TestObject);
var fieldType = test.GetField(fieldName);
if (fieldType != null)
{
var attribute = fieldType.GetCustomAttribute<FieldAttr>();
return attribute;
}
return null;
}
}
Usage:
TestObject test = new TestObject();
var attr = test.GetFieldAttr(x => x.testfld3);
if(attr != null) Console.WriteLine(attr.Text);
Here is the fiddle
After another day of trial and error I decided to make use of Selman22 answer with a little modification. This is code I created:
public class TestObject : iTestObject
{
// Declare fields
[FieldAttr("prop_testfld1")]
public FLDtype1 testfld1 = new FLDtype1();
[FieldAttr("prop_testfld2")]
public FLDtype2 testfld2 = new FLDtype2();
[FieldAttr("prop_testfld3")]
public FLDtype1 testfld3;
}
public class FLDtype1 : iField
{
public string Value { get; set; }
}
public class FLDtype2 : iField
{
public Guid Value { get; set; }
}
public sealed class FieldAttr: System.Attribute
{
private string _txt;
public FieldAttr(string txt)
{
this._txt = txt;
}
public string Text { get { return this._txt; } }
}
public interface iField { }
public interface iTestObject { }
public static class Extensions
{
public static FieldAttr GetFieldAttr<T>(this T source, Expression<Func<iField>> field) where T : iTestObject
{
// Get member body. If no body present, return null
MemberExpression member = (MemberExpression)field.Body;
if (member == null) { return null; }
// Get field info. If no field info present, return null
FieldInfo fieldType = typeof(T).GetField(member.Member.Name);
if (fieldType == null) { return null; }
// Return custom attribute
return fieldType.GetCustomAttribute<FieldAttr>();
}
}
Usage:
public class Program
{
public static void Main()
{
TestObject test = new TestObject();
Console.WriteLine(test.GetFieldAttr(() => test.testfld1).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld2).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld3).Text);
}
}
Uses:
using System;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;
I have implemented interfaces to protect the GetFieldAttr method
#Sulman22: Thnx for the response!