So what I'm trying to do here is pass the same copy of a class (class A) to another class (class B), but class B is instanced in class A.
Using a new statement in class B won't work because it would cause an infinite loop, as well as creating a new instance of it, when I want to be able to use variables from the 1st instance of class A.
I know about object.equals() but I can't use it until I define the class A's object in class B. Just using object.equals results in a null reference.
public partial class class_A : Form
{
public class_B _class_B = new class_B;
public Int32 var;
private void setclassA()
{
_class_B._class_A.equals(this);
}
}
public class class_B
{
public class_A _class_A; // I know this is null
// code
}
Like I said I want to avoid instancing a new copy of class A because I want the values in class A to be set.
I've tried using a method to do it but still get a null reference.
Pass A in the constructor of B:
public class A
{
private B _b;
public A()
{
_b = new B(this);
}
}
public class B
{
private A _a;
public B(A a)
{
_a = a;
}
}
As mentioned in the comments you're completely misunderstanding .Equals(). It's used to compare whether two objects are equal not clone / pass references.
Answer
You're 75% there. As Ron mentioned, just change .equals(this) to = this as follows:
_class_B._class_A = this;
Explanation
If we want to pass the same copy of ClassA to ClassB, and to do that when we instantiate ClassB inside of ClassA, then we use the this keyword, which represents the current instance of a class.
Though there are other ways to give this to ClassB, the below example shows two:
pass this to the constructor and do the property assignment in ClassB or
assign this directly to a property in ClassB.
The key for you is that = is an assignment operator whereas Equals() checks whether two variables refer to the same object or not.
Example
public class ClassA
{
public ClassB MyClassB1 { get; set; }
public ClassB MyClassB2 { get; set; }
public ClassA()
{
// pass `this` to the constructor
this.MyClassB1 = new ClassB(this);
// pass `this` directly to a property in `ClassB`
this.MyClassB2 = new ClassB();
this.MyClassB2.MyClassA = this;
}
}
public class ClassB
{
public ClassA MyClassA { get; set; }
public ClassB() { }
public ClassB(ClassA classA)
{
// do property assignment in the constructor
this.MyClassA = classA;
}
}
Proof of Concept
This runs as a Fiddle here and prints out "They are the same object," and some other things too in the more recent version.
using System;
public class Program
{
public static void Main()
{
var classA = new ClassA();
if(classA.Equals(classA.MyClassB1.MyClassA) &&
classA.Equals(classA.MyClassB2.MyClassA) &&
classA.MyClassB1.MyClassA.Equals(classA.MyClassB2.MyClassA))
{
Console.WriteLine("They are the same object.");
}
}
}
An important note is that, when we use this, we're giving ClassB a reference to ClassA not a copy of it. These are very different things.
Try this:
public class A
{
public B Instance_B;
public A(B b)
{
Instance_B = b;
}
}
public class B
{
public A Instance_A;
public B()
{
Instance_A = new A(this);
}
}
Use get; set;
In Class A:
public partial class class_A : Form
{
Class_B B = new Class_B();
B.Class_A = this;
public Int32 var;
}
Then in Class B:
public class class_B
{
Class_A A { get; set; }
// code
}
Related
I have a class A, and a class AStore. My requirement is to prevent all other methods from initializing an instance of class A, which they should get an instance from AStore. In addition, I also need to access the member functions of A from the instance.
Factory pattern is not suitable for this problem as the constructor of A is still public. Ideally, it should throw compilation error when calling the constructor of class A while having access to its member functions.
Can I get C# solutions to this?
For restricting others to create an instance of class A you can use a private constructor and a static factory method to get the instance of that class.
public class A
{
private A(){}
public static A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
To enforce instance creation of A only via Astore you can use protected modifier and derive AStore from A. That way, only AStore will have access to its protected members like 'constructor' or 'factory method':
public class Astore : A
{
public A GetInstanceOfA()
{
return base.GetInstance();
}
}
public class A
{
protected A() { }
protected A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
//Usage
public class ConsumerClass
{
public void Test()
{
var a = new A(); // Compile error
a = new Astore().GetInstanceOfA();
a.MemberFunctionOfA();
}
}
But there're still chances that another class say 'UnWantedStore' can derive from A and serve instance of A.
Another approach is moving AStore and A classes to the dedicated project and make constructor of A class internal.
// Project A
namespace ProjectA
{
public class A
{
public int PropertyOne { get; set; }
public string PropertyTwo { get; set; }
internal A() {}
}
public class AStore
{
public A CreateA()
{
//internal constructor can be used
return A();
}
}
}
// Project ConsumerOfA
namespace ConsumerOfA
{
public static void UseA()
{
var store = new AStore();
var instanceOfA = store.CreateA();
// have access to the A's public members
}
}
With this approach you will get perfect encapsulation you trying to achive.
Abstract classes to the rescue!
Indeed, there's yet another possible approach! I've never used it but it might work in your scenario. See the following code sample:
public abstract class A
{
public string Text { get; set; }
public string SayHello() => "hello world!";
}
public class AStore
{
private class AInternal : A {}
public void DoStuff()
{
A a = new AInternal();
a.Text = "whatever";
string helloText = a.SayHello();
}
}
Let's explain the approach:
Class A is abstract, therefore it can't be instantiated.
Class AStore implements a private nested class called AInternal which just inherits A to let AStore members be able to instantiate A. Since AInternal is private, no other class than AStore can instantiate AInternal!
Class AStore can access public A members because AInternal inherits A!
You can do this with reflection too:
public class ClassA
{
// The constructor(s) have to be private
private ClassA() { }
// Whatever other code you want
}
public class ClassB
{
public static ClassA GetClassAInstance()
{
// Use reflection to get the private default constructor
ConstructorInfo constructor = typeof(ClassA).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
ClassA instance = constructor.Invoke(new object[] { }) as ClassA;
return instance;
}
}
You can find more information on the GetConstructor method here.
I have a few classes. Lets say:
public class A
{
public void SomeAction()
{
Debug.Write("I was declared in class: and my name is:");
}
}
And
public class B
{
public static A myClass = new A();
}
public class C
{
public static A myClass = new A();
}
public class D
{
public static A myClass = new A();
}
What I want "SomeAction" in class A to do is to print out which class it was initialized in.
So that for example in another class I called C.myClass.SomeAction(); it would print out "I was declared in class C my name is myClass"
I hope this makes sense.
The reasons im doing this is for debugging within automated testing. I understand its not the best way to do things but its a requirement of the business.
This requirement can be satisfied without inheritance or passing the object; we can get the name of the class that calls the constructor from within the body of the constructor by examining the stack.
public class A
{
private string _createdBy;
public void SomeAction()
{
Console.WriteLine("I was declared in class [{0}]", _createdBy);
}
public A()
{
var stackFrame = new StackFrame(1);
var method = stackFrame.GetMethod();
_createdBy = method.DeclaringType.Name;
}
}
In terms of performance, I am assuming that you are not creating many instances of these objects. You could also predicate this on whether you are doing a DEBUG build or on some other setting, so that this stuff is skipped entirely in your production executables.
Since you only reference an instance of class A in your other classes, I think there is no other way then setting a reference to the type which created class A, like eddie_cat already mentioned. You could do something like this:
public class B
{
public static A myClass = new A(typeof(B));
}
And then your class A would look like:
public class A
{
// store the parent type
private Type mParentClass;
// provide parent type during construction of A
public A(Type parentClass)
{
mParentClass = parentClass;
}
// note that method cannot be static anymore, since every instance of A might
// have a different parent
public void SomeAction()
{
// access field where parent type is stored.
Debug.Write("I was declared in class: {0} and my name is:",mParentClass.Name);
}
}
I think you have two choices. Either set a property in A, or inherit from A. Personally, I prefer inheriting from A, because then A could just use GetType().
public class A
{
public void SomeMethod()
{
Debug.Write(string.Format("I was declared in class: {0}",this.GetType()));
}
}
public class B : A
{
}
var instanceOfB = new B();
instanceOfB.SomeMethod();
Assume I have a class A, and B which derives from A:
class A : ICloneable
{
public object Clone() {...}
}
class B : A, ICloneable
{
public object Clone() {...}
}
which gives
'B.Clone()' hides inherited member 'A.Clone()'. Use the new keyword if hiding was intended.
warning.
(1) What is the suggested way? using new or declaring A.Clone() as virtual and override in B?
(2) If there are some members in A and properly cloned in A.Clone(), is there an easy way to clone them in B.Clone() or do I have to explicitly clone them in B.Clone() also?
If you have access to your source (which I'm guessing is the case here) then absolutely declare it as virtual and override it. If hide the base Clone with new might be a bad idea. If any code doesn't know that it's working with a B, then it will fire the wrong clone method and not return a proper clone.
Regarding the assignment of properties, perhaps consider implementing copy constructors and each level can handle its own cloning:
public class A : ICloneable
{
public int PropertyA { get; private set; }
public A()
{
}
protected A(A copy)
{
this.PropertyA = copy.PropertyA;
}
public virtual object Clone()
{
return new A(this);
}
}
public class B : A, ICloneable
{
public int PropertyB { get; private set; }
public B()
{
}
protected B(B copy)
: base(copy)
{
this.PropertyB = this.PropertyB;
}
public override object Clone()
{
return new B(this);
}
}
Each copy constructor calls the base copy constructor passing itself down the chain. Each inheritance level copies the properties belonging to it directly.
EDIT: If you use the new keyword to hide the base implementation, here's an example of what might happen. With a sample implementation (which on the face of it looks fine)
public class A : ICloneable
{
public int PropertyA { get; protected set; }
public object Clone()
{
Console.WriteLine("Clone A called");
A copy = new A();
copy.PropertyA = this.PropertyA;
return copy;
}
}
public class B : A, ICloneable
{
public int PropertyB { get; protected set; }
public new object Clone()
{
Console.WriteLine("Clone B called");
B copy = new B();
copy.PropertyA = this.PropertyA;
copy.PropertyB = this.PropertyB;
return copy;
}
}
But when you use it:
B b = new B();
A a = b;
B bCopy = (B)a.Clone();
//"Clone A called" Throws InvalidCastException! We have an A!
I have the following scenario in C#
public class classA
{
public int fieldA = 1;
public classA()
{
classB b=new classB();
b.Execute();
}
}
public class classB
{
public Execute()
{
//I can get the type of classA using
FieldInfo fi = stackTrace.GetFrame(1).GetMethod().DeclaringType
}
}
The question is how do I get the reference of classA that invoked the Execute in the instance of classB?
I tried using reflection but could not find any way to do it.
Any help would be much appreciated
You can send a the reference of A to B in execute method like this:
b.Execute(this);
you can reach the object A by this way.
Change class B like this
public class B
{
public Execute(A aObj)
{
//class A Object is available here
}
}
Change Class A like this
public class A
{
public A()
{
B b = new B();
b.Execute(this);
}
}
I have a BL class named:A , DTO class named:DTO . Now assume I want to add some more properties in my DTO. So I derive a new DTO class from my existing DTO and add properties to it.Below is the code:
namespace TestConsole
{
class test
{
static void Main(string[] args)
{
B b = new B();
b.D.ID = 1;
b.D.Name = "4";
MyBLMethod(b);
}
static void MyBLMethod(A b)
{
MyDALMethod(b.D);
}
static void MyDALMethod(DTO dto)
{
int i = dto.ID;
string name = ((MyDTO)dto).Name;//I could not do this
//because i will get object cast error as i can't cast from
//parent to child
}
}
public class DTO
{
public int ID = 99;
public DTO()
{
}
public DTO(DTO source)
{
ID = source.ID;
}
}
public class MyDTO : DTO
{
public string Name = "";
public MyDTO() { }
public MyDTO(MyDTO source)
: base(source)
{
Name = source.Name;
}
}
public class A
{
private DTO _d;
public A()
{
D = new DTO();
}
public DTO D
{
get { return _d; }
set { _d = value; }
}
}
public class B : A
{
private MyDTO _md;
public B()
{
_md = new MyDTO();
}
public MyDTO D
{
get { return _md; }
set { _md = value; }
}
}
}
From Main (you can think it as UI) i am calling MyBLMethod (present in BL repository) and passing class object to it , and from BL repository i am calling my DAL. In DAL i have written this:
static void MyDALMethod(DTO dto)
{
int i = dto.ID;
string name = ((MyDTO)dto).Name;//I could not do this
//because i will get object cast error as i can't cast from
//parent to child
}
Could you suggest me how could i get the newly extended property (name in the example) in my DAL.
When B inherits A, it already owns a DTO attribute. So the problem is really that you are hidding this inheritance. You don't need a new property inside B class, just set it in your class constructor.
public class B : A
{
public B()
{
this.D = new MyDTO();
}
}
But, in your main class you will need a explicit cast in your property, just like below, since DTO does not have a "Name" property.
static void Main(string[] args)
{
B b = new B();
b.D.ID = 1;
((MyDTO)b.D).Name = "4";
MyBLMethod(b);
}
If the object is ACTUALLY of the base type, you can't just tack on the additional properties. Doesn't work that way, sorry.
What you want is to CONVERT the object (maybe). Make a constructor in your child class that can take a parent and copy all of it's stuff into itself - then you'll have the additional properties.
The reason that the cast fails, is that you are not passing a MyDTO object to the method, but a DTO object. The MyBLMethod method always sends the DTO object to the DAL even if there is a MyDTO object.
You haven't made the D property virtual. That means that when you use the D property on an A reference, you get the DTO object that the A class contains even if the actual object happens to the a B instance so that it also has a MyDTO object.
You can make the D property virtual to access the D property of the actual object instead of the one specified by the type of the reference.
Or you can cast the reference to B so that you can access it's MyDTO object instead of it's DTO object:
static void MyBLMethod(A b) {
MyDALMethod(((B)b).D);
}
Note that the B class contains both a DTO and a MyDTO object, which might not be what you really want.
It sounds like you are losing "resolution" because you are passing through a static business logic method. I would suggest revisiting that part rather than struggling with the DAL method first.
There may be a reason you're stuck with that though, so if you are, you can consider using reflection to find the properties you need or using an "as" cast and then testing for null in your dal method. If you aren't stuck with this design, I'd refactor my way out of the static method though. Static seems so easy and unfortunately there's a lot of code 'quality' tools pushing you to make methods static which forget to remind you can't easily change static methods to virtual methods later.
Allow B to pass A a DTO object in A's constructor. If needed, make the constructor protected. Then, have B.D cast A.D.
public class A
{
private DTO _d;
// New constructor.
protected A(DTO d)
{
_d = d;
}
// Old constructor calls new constructor.
public A() : this(new DTO())
{
}
public DTO D
{
get { return _d; }
set { _d = value; }
}
}
public class B : A
{
// Old B constructor calls new A constructor.
public B() : base(new MyDTO())
{
}
new public MyDTO D
{
// Getting D casts A.D instead of using an object exclusive to B.
get { return (MyDTO)base.D; }
set { base.D = value; }
}
}