I asked a question on here earlier but I didn't explain correctly so I got the right answers to the wrong question.
I am creating an instance of a class, when I get the class back it returns a number of results which are private in the class I am calling.
I am unable to change this class and make them public for various reasons.
What I need to do is enumerate through and get a value of the Text variable that is held:
public class StringReader
{
private string LongText = "this is the text i need to return";
private string Text;
public StringReader()
{
Text = LongText;
}
}
In the method I am trying to get the value of Text I am calling
StringReader sReader = new StringReader();
List<StringReader> readers = new List<StringReader>() { sReader};
Readers has LongText and Text but I am struggling to get the text value back.
Instead it just returns the Type to me.
You will need to use reflection to access the private field. You can access all fields of a type using the GetField(s) method. You can access their values using the GetValue function
public string GetLongText(StringReader reader)
{
// Get a reference to the private field
var field = reader.GetType().GetField("LongText", BindingFlags.NonPublic |
BindingFlags.Instance)
// Get the value of the field for the instance reader
return (string)field.GetValue(reader);
}
Fields declared as private are inaccessible outside the class that defined them. You cannot read their value without either
Changing their visibility
Adding an accessor method/property with public visibility
Using reflection (this is not recommended, there is almost always a better way)
What is the use-case here? What are you trying to achieve? If you define your problem a bit more generally maybe we can give a better solution.
Without modifying the class, it's impossible using best OOP practices. They are set to private to mean they can only be accessible inside the class only. You need to speak to the original developer of the class and ask why they cannot make a public getter for the private field that would look like this:
public string getText(){
return this.Text;
}
This would mean the string can't be modified, but you can at least read it.
Related
To simplify the case, let say I have the following class
public class TestFileHelpersClass
{
[FieldOrder(1), FieldFixedLength(20), FieldTrim(TrimMode.Both)]
public string Field1 { get; set; }
[FieldOrder(2), FieldFixedLength(20), FieldTrim(TrimMode.Both)]
private string Field2 { get; set; }
// If change to a normal variable, there is no exception and FileHelper can work perfectly.
// private string Field2;
public TestFileHelpersClass()
{
this.Field1 = "Field1 Value";
this.Field2 = "Field2 Value";
}
}
Then, there is an exception thrown when I instantiate the FileHelperEngine.
static void TestFileHelpers()
{
// FileHelpers.BadUsageException: 'The field: '<Field2>k__BackingField' must be marked with the FieldFixedLength attribute because the record class is marked with FixedLengthRecord.'
FileHelperEngine<TestFileHelpersClass> engine = new FileHelperEngine<TestFileHelpersClass>();
TestFileHelpersClass a = new TestFileHelpersClass();
string result = engine.WriteString(new List<TestFileHelpersClass> { a });
}
But {Field2} has already been marked with {FieldFixedLength(20)}
If I change {Field2} from a property to variable, it is working fine.
The question is:
When it is public, FileHelpers works perfectly in both the variable and property case.
When it is private, variable is still ok, but property fails to work.
Any idea why private property and variable behave differently in FileHelpers?
When you write autoprops, the compiler generates backing fields for you:
FileHelpers has ReflectionHelper.cs that picks up the fields in a type you want it to parse:
This means, for my dumb class in the first screenshot, it will pick up the two __BackingField, and the two normally named fields:
When FileHelpers is processing these in FieldBase.cs, for any backing fields that have a friendly name, it goes for the property:
fi is the __BackingField; it does have a friendly name because it's come from PrivateProp. To go for the property, FH calls this:
var prop = fi.DeclaringType.GetProperty(fieldFriendlyName);
This call won't discover a private property because it doesn't specify any BindingFlags.NonPublic|BindingFlags.Instance, so prop ends up null and FH doesn't switch to looking at the property
Look back at the first image; the FileHelper custom attributes are on the property, not the backing field. Later in this same FieldBase.cs class, FH tries to find derivates of its own attributes (FH's attributes derive from FieldAttribute) on the member being inspected:
The member being inspected is the __BackingField, which doesn't have any FH attributes; it's the prop that has the attributes. The field does have attributes (CompilerGenerated, DebuggerBrowsable) but because this call looks only for FH's attributes and the backing field doesn't have any FH custom attributes it is essentially looking on the wrong thing. It reaches a situation where it cannot work - it needs attributes you've put on the prop, but it looks on the field, finds no FH attribs and throws an error because it needs those attributes it can never find.
If fi.DeclaringType.GetProperty(fieldFriendlyName) had instead used an overload that looked for private props e.g. fi.DeclaringType.GetProperty(fieldFriendlyName, BindingFlags.NonPublic|BindingFlags.Instance|..other_binding_flags_here) then it would have found the private prop you decorated (but I don't guarantee that this is a bug or that that is the resolution)
You could report a bug and see if the author agrees, you could amend the library yourself and use the amended version, or you could just use fields/public props instead of private props
I cannot answer why the library was coded this way; few people here can. Questions of the ilk "what was developer X thinking when..." are seldom a good fit for SO.
My question is: Can I define a static method "meth1" in a static class "classB" that, when called from "classA", searches for a specific field (in "classA", not in the class in which is defined)?
I try to explain better: I need to do something like this:
public class classA
{
string someText;
int anInt;
bool trueOrFalse;
public classA()
{
...
...
var variable = classB.meth1("variableName");
...
...
}
}
public static classB
{
public static object meth1(string name)
{
...
... //use "name" to find the variable with that name in the class from which "meth1" is called.
...
}
}
That because I have to read a backup of "last run values" of variables contained in a .txt file, written line by line as "variable name = value".
So I read the .txt, create an hashtable "backupHashtable" which contains ("variable name";"value"), and then I want to search variables by string "variable name" and reset them to "value".
If someone of you knows a better procedure I'm listening. Maybe the use of a Dictionary?
Thank you!
UPDATING
Ok, now I have a clearer idea of what I want to do: I want to implement a class "ClassB", separate from my main class "classA". In this new class I would have a "meth1" method which, running in a separate thread, saves every 10 seconds (for example) the state of some variables belonging to "classA". To communicate the "meth1" what are the variables that he has to save, I want to use a list containing the names (in the format "string", that's what I thought, but I guess it's not the only way) of these variables.
If you're wondering why I want to do this in a separate thread the answer is this: my application performs some recognition operation of some objects in live stream images from multiple cameras and then ancillary operations must be isolated as much as possible from the main code to increase the speed of execution.
Now, perhaps, it is more understandable what I said before.
Yes, but you also need to pass a reference to the instance of A. Then use reflection to get or set the property.
public static void Meth1(object obj, string propertyName)
{
var prop = obj.GetType().GetProperty(propertyName);
var value = prop.GetValue(obj);
...
}
If I were to get values from a textfile into a class, I think I'd load them in a dictionary first, and then set all properties one by one. (Maybe unless there are, say, hundreds of properties). When using reflection, there is a chance that the textfile contains the name of a property you don't want to be changed from outside.
object value;
if (dict.TryGetValue("someProperty", out value)) { a.SomeProperty = value; }
So, i'm not sure what i'm doing wrong here but for some reason the callback function in TypeScript that i have doesn't have anything but _proto in the response's .data property whenever i set private properties in C# and new up an object that is filled with constructed properties. However, if the properties are public and i don't use a constructor then i can see the response's .data property is filled like i would expect it to be. Here is an example of what works:
public class ThisWorks{
public string MyProperty{get;set;}
}
Inside application layer:
ThisWorks example = new ThisWorks();
example.MyProperty = myReflectedProperty;
return example;
However, this does not work:
public class ThisDoesNotWork{
private string MyPrivateProperty {get;set;}
public ThisDoesNotWork(string myPrivateProperty){
MyPrivateProperty = myPrivateProperty;
}
}
What's causing this to happen? My TypeScript service has not changed but for some reason the data isn't coming across from the service call...Any help would be greatly appreciated! Also, Serialization is NOT constructive for this thread.
If you want to control access to a property, you can normally do this very will without a method in C#...
It appears that you want the ability to set the property, but not read it. The following is an example of a public write-only property, which you can read and write in private context.
This appears as a property to callers, rather than a method.
public class Example
{
private string _exampleProperty;
public string ExampleProperty
{
set { _exampleProperty = value; }
}
}
I'm fairly new to C# but have extensive experience in Objective-C and OOP. I'm using Json.NET to automatically parse API responses to objects. It so happens that one of the objects returned has a property named protected. Obviously this is a problem, because protected is a keyword for class member declaration.
"protected": true
Is it possible to add a member with the name protected at all?
Is it possible to add setters and getters that get triggered, if the parser tries to set the protected property? (but assign the value to a private member named _protected)
Should I modify the parser to behave different when he encounters a property named protected?
Thanks for any advice.
1:
For question #1: You can put an # symbol before it any keyword you want to use as a variable name.
E.g.
public string #protected {get; set; }
I recommend against doing this, however. You should be able to remap the "protected" field in your JSON to a different property in your POCO.
2:
private string _protected;
public string #protected
{
get
{
//any additional code you want
return _protected;
}
set
{
//any additional code you want
_protected = value;
}
}
3:
Up to you!
I implemented this solution:
[JsonProperty("protected")] public bool Protected { get; set; }
Like Daniel Mann suggested in his comment:
1) I'm still quite new to programming and have read a bit about getters and setters. But I really don't understand why they are used.. Could anyone explain it, or point me to an article? (The ones I read were not really understandable for me...)
2) In my current project I have a class where I declare and initialize an array of structs. I now need to access the array from another class, but it gives me the error: An object reference is required to access non-static member 'BaseCharacter.Attributes'.
I figures this could mean I need to use getters and setters? But how does this work for arrays?
Thanks in advance!
Simon.
EDIT: 2nd question got solved, which brings me to something else. When I want to use some class in another one, I'm making a new instance of the class, right? And this means I get the original values?
But that's not what I want.
The second class is used to generate the UI, and needs the values I'm keeping in the first class.
At some point I will implement save files (XML or even on a server in later stage). Can I then just get the values from those files?
For the getters and setters (the things that use them are called Properties) it's just a convenient and nice-looking way to make people think they're using a variable, but to do some computation whenever the variable is updated or accessed. For instance:
BankAccount.Interest
looks better than
BankAccount.GetInterest()
Even though you can calculate the interest at the time it is requested in both cases.
They are also used to make a variable be able to be accessed from outside the class, but changeable only from within the class with this technique:
public double Interest {
get;
private set;
}
For an example of a setter being used, if you've ever used Windows Forms and updated a control's Height or Width property, you're using a setter. While it looks like you're using a normal instance variable like c.Height = 400, you're really letting c update it's position by redrawing at a new place. So setters notify you exactly when a variable is changed, so your class can update other things base on the new value.
Yet another application of Properties is that you can check the value people try to set the property to. For instance, if you want to maintain an interest rate for each bank account but you don't want to allow negative numbers or numbers over 50, you just use a setter:
private int _interestRate = someDefault;
public int InterestRate {
get { return _interestRate; }
set {
if (value < 0 || value > 50)
throw new SomeException(); // or just don't update _interestRate
_interestRate = value;
}
}
This way people can't set public values to invalid values.
For your second question, you can do one of two things depending on what you're trying to do.
One: You can make that member static. That means that just one of them exists for the entire class instead of one per instance of the class. Then you can access it by ClassName.MemberName.
You can do that this way:
// inside the BaseCharacter class definition:
public static SomeStruct[] Attributes = new SomeStruct[size];
// then to use it somewhere else in your code, do something with
BaseCharacter.Attributes[index]
Two: You have to make an instance of the class and access the array through that. This means that each object will have its own seperate array.
You'd do that like this:
BaseCharacter bc = new BaseCharacter();
// use bc.Attributes
The second one is probably what you'll want to do, since you probably will want to modify each character's attributes seperately from all the other characters.
Actually the error you mention is not related to the getters and setters concept, it's because after creating your class you need to create an object before using its members; think of the class as a template for a document and the object as the document
you are most likely doing something like this:
var someVar = BaseCharacter.Attributes;
When you should be doing something like this:
var someVar = new BaseCharacter();
var someOtherVar = someVar.Attributes;
And about why the getters and setters, Seth Carnegie's Answer covers it nicely.
If you are new to Object Oriented Programming, you may be missing an important concept, that is about encapsulation.
Fields (attributes) of a class should be accessed only from within the class (or it's inherited classes). That is, if we have a class person, only with a name, you can do
public class Person
{
public string Name;
}
So anywhere in your program, you will be able to access it by doing:
Person person = new Person();
person.Name = "Andre";
This works, but it's not encapsulated. In some languages like C++ or Java, it was done like this:
public class Person
{
private string _name;
public string setName(string newName)
{
this._name = newName;
}
public string getName()
{
return this._name;
}
}
Person person = new Person();
person.setName("Andre");
This makes our _name attribute encapsulated, it can only be retrieved by it's get and set methods (that is, by the interface of the class).
C# makes this easier, allowing getters and setters:
public class Person
{
private string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
Person person = new Person();
person.Name = "Andre";
This is very much like the second example (Java/C++ way), but you treat Name as property, instead of methods, and leaving our name property encapsulated
1) They might seem optional but they allow you more control over code:
You're able to intercept new values and avoid them being set (e.g. to exclude pointless values). Also you're able to fire custom events in case a property is changed or updated (just like the WinForms controls do).
private string name;
public string Name
{
get
{
// running additional code, e.g. here I avoid returning 'null' for a name not set
if(name == null)
return "(Unknown)";
return name;
}
set
{
// checking incoming values, e.g. here I avoid setting an empty name
name = value != null && value.Length > 0 ? name : null;
// running more/additional code, e.g. here I raise an event
if(OnNameChange)
OnNameChange();
}
}
2) Without knowing the code it's hard to tell you the exact reason, but if you'd like to access some member variable or property you have to either create an object of that class or make the variable static (e.g. shared between all instances of the object):
class MyClass
{
public static int someNumber = 55;
public int thisNumber;
}
// ...
int someothervar = MyClass.someNumber; // access the static member variable
MyClass mc = new MyClass(); // create an object of the class
int yetanothervar = mc.thisNumber; // access the member variable