Get the parent class of a null object (C# Reflection) - c#

How would I get the parent class of an object that has a value of null?
For example...
ClassA contains int? i which is not set to any value when the class is created.
Then in some other place in the code I want to pass in i as a parameter to some function. Using i as the only info, I want to be able to figure out that ClassA "owns" i.
The reason for this is because ClassA also contains some other object, and I want to call this other object's value from that same function mentioned in the above paragraph.
Could also be:
public class A
{
public class B
{
public int? i;
public int? j;
}
B classBInstance = new B();
public string s;
}
{
...
A someClassAInstance = new A();
...
doSomething(someClassAInstance.classBInstance.i);
...
}
public static bool doSomething(object theObject)
{
string s = /* SOMETHING on theObject to get to "s" from Class A */;
int someValue = (int)theObject;
}

You can't. Pass an instance of A to doSomething.

class A is not the Parent (base) of its members. Just their holder.
So you cannot do what you want, passing an int or int? around doe not involve any information about the class.

The parameter that is sent to the method doesn't contain any information that you can use to determine which object it originally came from. What's sent to the method is just a copy of the nullable int, boxed in an object.
So what you are asking for is not possible. The only way to do something like that would be to analyse the call stack to find the calling method, then analyse the code in that method to determine where the parameter value was taken from.

Cant you use a dictionary or keyvaluepairs instead so that the int is linked to "s" that way? The problem is that an int is not aware of which object owns it.

Its not possible since you are passing 'i' which is a member of class B. But class B does not hold a reference to an instance of class A. An instance is required to get the value of 's' since its a non-static field.

Related

Create ref on struct

I want to send a reference to a struct to a form. Then I need to store the reference so I can do changes to a member of that struct before the form is closed. Here's the code:
struct mystruct
{
public int myvar;
}
public partial class myForm : Form
{
private mystruct refonstruct;
public myForm(ref mystruct ms)
{
// refonstruct will be a copy, not a reference :-(
refonstruct = ms;
// how can I get a reference instead?
}
public myForm_FormClosing()
{
// since refonstruct is not a reference the next line will not change foostruct
refonstruct.myvar = 17;
}
}
public void foo()
{
mystruct foostruct;
foostruct.myvar = 0;
using(myForm f= new myForm(ref foostruct))f.ShowDialog();
// here foostruct, myvar will still be 0 since refonstruct is a copy not a reference
}
Passing a struct as refernce in the constructor is not the problem. If I would be able to do changes to the member of the struct there (ms.myvar = 17) it would work. But I can only apply the changes before closing the dialog. In case I could use a class instead all would be no problem, I know, but I for so many reasons (e.g. existing huge project, file format, etc.) I cannot. Summary: Is there a way to store a reference to a struct in a member variable? Thanks.
If you want forms to share data a struct is not the correct approach to use. Structs are value types, and stored in the context where they are used. This would be the stack frame of foo() in this case. Since myForm is a class, it can have a longer lifetime than foo(). So if it could store a reference, that reference might be invalid and refer to some random position on the callstack, and that is just not allowed.
The easiest option is to just change mystruct to a class.
An alternative is to introduce a wrapper around the struct:
public class Ref<T>
{
public T Value { get; set; }
public Ref(T value) => Value = value;
}
That way your struct can be immutable, and you would just replace the entire struct when it needs to change. You can also add an event that is raised when the value is set, to let any form know if it needs to update itself to show the updated value.

Reference another class member

I have three classes (Data, First, Second ).
I'm creating member of Data in First and try to pass it to Second with the following:
public class First
{
public Data DataMember;
Second SecondMember;
void First_Function()
{
SecondMember.Second_Function(ref DataMember);
}
}
public class Second
{
Data DataMember;
public void Second_Function(ref Data data)
{
}
}
Is there a way to access the First.Data member in Second.Data member?
Using ref in the Second.Second_Function() allows me to access the member of the First but only inside the Second_Function().
I want another function in Second to access it, that has a different "call back time" as the Second_Function().
Edit :
My question in not about what is the difference between the reference and value type .
if I use ref keyword for a int variable , that mean if I replace it with another value it will effect the original .
in class when I have two variable reference to the same instance if I edit one of them I effect the other , that's because they reference to the same thing ,I want to know if there is a way in C# to replace one of the variable ,and make the other variable change with it .
There are two kinds of types in C#: reference types and value types.
Variables of reference types store references to their data (objects),
while variables of value types directly contain their data. With
reference types, two variables can reference the same object;
therefore, operations on one variable can affect the object referenced
by the other variable. With value types, each variable has its own
copy of the data, and it is not possible for operations on one
variable to affect the other (except in the case of ref and out
parameter variables, for more details see here
Here an example:
Explanation
Pass your data object to the class First, Second as parameter in the constructor
Any updates happens on the data object inside First or Second will be reflected on the data object outside these classes because it is reference type
public class Data{
public Data(int value)
{
this.Value = value;
}
public int Value{get;set;}
}
public class First{
private Data m_data;
public First(Data data)
{
m_data = data;
}
public void Add(int value)
{
if(m_data!=null)
m_data.Value+=value;
}
}
public class Second{
private Data m_data;
public Second(Data data)
{
m_data = data;
}
public void Multiply(int value)
{
if(m_data!=null)
m_data.Value*=value;
}
}
now let us setup this scenario
var data = new Data(10);
var first = new First(data);
var second = new Second(data);
second.Multiply(5);
first.Add(10);
What do you expect the value inside the class data? 10? you are wrong, the value is 60
Here a working demo
Hope this will help you

Data type for a variable that can be different types

I am new to C# but seem to have noticed a limitation from what I am wanting to do with my code.
I have a class which i want to store a reference to other classes which i plan to store in a list. Something like this:
myList.Add(new Node(1,1,referenceToClassA));
myList.Add(new Node(1,2,referenceToClassB));
So my class would look like this:
public class Node : IHeapItem<Node> { //IHeapItem is for a heap i use for pathfinding
public int x;
public int y;
public ??? reference;
// constructor
public Node(int a, int b , ??? r){
x = a;
y = b;
reference = r;
}
// other unrelated stuff
}
So as you can probably guess, i have no idea what data type reference would be in my class given that it could be assigned to different classes.
I can't seem to find if there is a data type that is flexible for this in C# (i started in JavaScript so am not used to strict behavior on variable types).
What are my options here, what data type should I use, or will i have to implement this in a totally different way?
Hope you can help.
IF you only have one type of item in each list, then you could use this:
public class Node<T> : IHeapItem<Node> { //IHeapItem is for a heap i use for pathfinding
public int x;
public int y;
public T reference;
// constructor
public Node(int a, int b , T r){
x = a;
y = b;
reference = r;
}
// other unrelated stuff
}
If you don't know what you're going to get, and you will have more than one item in a list, then you're forced to use object. With a little reflection, that can work out pretty well.
It is also possible that you will have sets of different items, each set could implement the same interface, then that interface could be what you hold in the list.
If you're trying to create a generic, use T as the parameter type.
If you use T as the parameter type, you'll have to modify your class to be Node<T> as well.
Otherwise, you could use dynamic.
There is a class called Object that can reference any other class. If you want to make it just to a little group of classes, you may want to create an abstract class or an interface.

property change notification in generic property

Rephrased the question. Scroll down for the original
Ok, maybe I should have given you the whole picture. I have many classes which look like this:
public class Movement : Component
{
private Vector3 linearVelocity;
public Vector3 LinearVelocity
{
get
{
return linearVelocity;
}
set
{
if (value != linearVelocity)
{
linearVelocity = value;
ComponentChangedEvent<Movement>.Invoke(this, "LinearVelocity");
}
}
}
// other properties (e.g. AngularVelocity), which are declared exactly
// the same way as above
}
There are also classes called Transform, Mesh, Collider, Appearance, etc. all derived from Component and all have nothing but properties which are declared as described above. What is important here is to invoke the ComponentChangedEvent. Everything works perfectly, but I was looking for a way where I don't have to rewrite the same logic for each property again and again.
I had a look here and liked the idea of using generic properties. What I came up with looks like this:
public class ComponentProperty<TValue, TOwner>
{
private TValue _value;
public TValue Value
{
get
{
return _value;
}
set
{
if (!EqualityComparer<TValue>.Default.Equals(_value, value))
{
_value = value;
ComponentChangedEvent<TOwner>.Invoke(
/*get instance of the class which declares value (e.g. Movement instance)*/,
/*get name of property where value comes from (e.g. "LinearVelocity") */);
}
}
}
public static implicit operator TValue(ComponentProperty<TValue, TOwner> value)
{
return value.Value;
}
public static implicit operator ComponentProperty<TValue, TOwner>(TValue value)
{
return new ComponentProperty<TValue, TOwner> { Value = value };
}
}
Then I would use it like this:
public class Movement : Component
{
public ComponentProperty<Vector3, Movement> LinearVelocity { get; set; }
public ComponentProperty<Vector3, Movement> AngularVelocity { get; set; }
}
But I am not able to get the instance where LinearVelocity comes from nor it's name as string. So my question was, if all of this is possible...
But it seems that I have no option other than keep doing it the way I was, writing this logic for each property manually.
Original Question:
Get instance of declaring class from property
I have a class with a property:
public class Foo
{
public int Bar { get; set; }
}
In another context I have something like this:
Foo fooInstance = new Foo();
DoSomething(fooInstance.Bar);
Then, in DoSomething I need to get fooInstance from having nothing but parameter. From the context, it is save to assume that not any integers are passed into DoSomething, but only public properties of ints.
public void DoSomething(int parameter)
{
// need to use fooInstance here as well,
// and no, it is not possible to just pass it in as another parameter
}
Is that possible at all? Using reflection, or maybe a custom attribute on the property Bar?
Why do you want to send just a property to DoSomething, send it the whole object :), so it would become,
DoSomething(fooInstance);
Your function will then accept object instead of parameter. You can use an overload of this function to make sure that old code doesn't break.
There are several ways to deal with implementing INotifyPropertyChanged. You're doing almost the same thing, except you don't implement the interface and raise the event in a different way. But all of the solutions apply for you too.
Like you do, call a method with a string parameter: OnPropertyChanged("Property").
Call a method with a lambda that uses the property: OnPropertyChanged(() => Property). The advantage of this is that it's compile-time checked for typos and refactoring-friendly.
Use caller information to inject the name of the property: OnPropertyChanged(). This will work in C# 5.
Use something like Castle DynamicProxy to create a derived class at runtime that will call the method for you. This means you need to make your properties virtual and that you need to create instances of the class only through Castle.
Use an AOP framework to modify the code of your properties after compilation to call the method.
there's no way to get fooInstance from parameter. parameter is passed by value, and is only a copy of the value of fooInstance.Bar, it no longer has anything to do with fooInstance
That being said, the obvious solution is to write DoSomething like this
public void DoSomething(Foo parameter)
{
// need to use fooInstance here as well,
// and no, it is not possible to just pass it in as another parameter
}
Property is just a field, which returns reference to some object on heap (i.e. its address). If property is not of reference type, it returns value of object.
So, when you do something like
DoSomething(fooInstance.Bar);
You just passing address of object Bar to method.
If Bar is reference type (i.e. class). Imagine that Mr.Foo has an address of Mr.Bar (462 for Marion County, Indiana). Mrs.CLR asks Mr.Foo for address of Mr.Bar. And then tells this address to somebody who needs address of Mr.Bar. How somebody will know, that CLR asked Foo about address of Bar? He received only an address 462 for Marion County, Indiana.
In case of value objects (int, double, structs etc), Mr.Foo has a cool mp3 track named Bar. Mrs. CLR creates a copy of that mp3 track and sends it to somebody. How somebody will know, that his mp3 track Bar is a copy of Mr.Foo's track?
So, if you want somebody to know about Mr.Foo, you need to pass an address of Mr.Foo to him:
DoSomething(fooInstance);
With this address somebody can visit Mr.Foo and ask him about address of Mr.Bar, or create a copy of his mp3 track :)

C#: Reflection: Get class object is created in

I am looking on how to get the object (or object type) that another object is created in. For example:
public class RootClass
{
public class A
{
public void MethodFromA()
{
}
}
public class B
{
public A A_object = new A();
public void MethodFromB() { }
}
B BObject = new B();
A rootAObject = new A();
public void DoMethod(A anA_object)
{
}
main()
{
/* Somehow through reflection
* get the instance of BObject
* of type B from only the info
* given in anA_object or at
* the very least just know that
* anA_object was created in
* class B and not root. */
DoMethod(BObject.A_object);
/* Same as above except know that
* this A object came from root
* and is not from B class */
DoMethod(rootAObject);
}
}
Additional Information:
This was just a quick code to simulate part of a large project I have. The problem is I have a custom class that is instantiated many many places in various other classes. This custom class has a function that should be able to call any function in it or any function in the class that instantiated it. Very generic processing, but needed. Basically I need the inverse of ".". So with objectA.objectB, I need to find objectA only from passing in objectB to some function.
Thanks!
No - this information isn't stored anywhere. Note that even if it were, it could easily become out of date, effectively. For example:
// Code as before
BObject.A_object = rootAObject;
rootAObject = null;
DoMethod(BObject.A_object);
What should that now show? The current value of BObject.A_object was created as rootAObject, but the current value of rootAObject is null. If you'd want that to show BObject as the "owner" then you're not really talking about creation at all... and at that point, you need to deal with the possibility that an object has multiple references to it.
Please give us more information about the bigger picture: what problem are you really trying to solve?
I believe what you're looking for is the property DeclaringType, defined on the System.Type instance that you're interested in. See DeclaringType documentation.
DeclaringType will only tell you the enclosing type of the code model, but what you are after is identifying object creation point.
There is no easy way to do it other than reading the individual MethodBody IL. IL code for creating an object is newobj. To implement this, you will need to read the MethodBody for every method in your assembly and identify the method that contains newobj instruction with type operand of the object type you are after.
Solved by making all my objects derive from a custom object with a parent parameter.

Categories