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; }
}
}
Related
is there a method to tell a method which type a generic has? what i want to do is to tell the method it can be only an object of type A or B but nothing else, so i can work within like
if (myObject.GetType() == typeof(myTypeA)){doAstuff();}
if (myObjectGetType() == typeof(myTypeB)) {doBstuff();}
method<T>(T myObject){ T = myTypeA, T = myTypeB, T = nothing else}
thanks for any help
You could check for the type inside the method, then cast it to the appropriate type and do the appropriate "stuff":
public void method<T>(T myObject)
{
if (myObject is myTypeA)
{
myTypeA objA = myObject as myTypeA;
objA.DoA_Stuff();
}
else if (myObject is myTypeB)
{
myTypeB objB = myObject as myTypeB;
objB.DoB_Stuff();
}
else
{
return ;
}
}
But that would be a waste of generics. If they share some methods you could also make a base class, and let typeA and typeB inherit from it. Then your method could take a base class object as parameter:
public void method(BaseClass myObject)
and there would be only one if - case and one casting. Only the one with more methods then the base class.
EDIT:
Imagine you would have such a structure:
public class BaseType
{
public int SharedProp { get; set; } // shared property
public virtual int DoSharedStuff() // shared method
{
return SharedProp;
}
}
public class myTypeA : BaseType
{
public int A_Prop { get; set; }
// overwritten shared meth adjusted to the needs of type A
public override int DoSharedStuff()
{
return base.SharedProp + this.A_Prop;
}
}
public class myTypeB : BaseType
{
public int B_Prop { get; set; }
// overwritten shared meth adjusted to the needs of type B
public override int DoSharedStuff()
{
return base.SharedProp + this.B_Prop;
}
// individual method of Type B
public int DoB_Stuff()
{
return this.B_Prop;
}
}
Then you method would take only one of the children of the base class and execute according to the needs:
public void method(BaseType myObject)
{
// shared case: here type A will perform type A action
// and type B will perform type B action
myObject.DoSharedStuff();
// case B where you need really the extra stuff!
if (myObject is myTypeB)
{
myTypeB objB = myObject as myTypeB;
objB.DoB_Stuff();
}
}
This approach or phenomenon is called Polymorphism
You can restrict the allowed types for a gernic with the where command:
public void Test<T>(T param) where T : TypeA {
...
}
https://learn.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
But this are only simple constraints so it does not solve the problem for two classes but for this case you can use method overloading:
public void Test(TypeA param) {
...
}
public void Test(TypeB param) {
...
}
If you have only two classes I think that is the best solution because generics would have no benefits.
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
}
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();
Let's say I have the following class hierarchy (base interface included):
IAction -> (abstract) BaseAction -> (concrete) ImmediateAction -> (concrete) MovementAction
Now, let's say IAction exposes a method (well, really a different interface that IAction implements does but let's keep things simple here!):
// Returns a new IAction instance deep copied from the current instance.
IAction DeepClone();
Good so far? We have our deep copy method, and ImmediateAction has some properties that it wants copied so it will provide not only an implementation of DeepClone(), but a copy constructor as well:
//Base Action implementation
protected BaseAction(BaseAction old)
{
this.something = old.something;
}
//Immediate Action Implementation
protected ImmediateAction(ImmediateAction old)
: base(old)
{
this.anything = old.anything;
}
public IAction DeepClone()
{
return new ImmediateAction(this);
}
Now, let's say MovementAction doesn't have anything inside of it that's relevant in a DeepClone() at all, so it doesn't implement the method or a copy constructor.
The problem that I'm having is this:
IAction x = new MovementAction();
IAction y = x.DeepClone();
//pleaseBeTrue is false
bool pleaseBeTrue = y is MovementAction;
Now, I understand what's going on here - MovementAction does not implement DeepClone(), so ImmediateAction.DeepClone() is called instead, which instantiates a new ImmediateAction. Hence, the type of y in the above example is ImmediateAction instead of MovementAction.
So, after this lengthy preamble, my question is this: what is the best practice for this type of situation? Am I stuck? Do I simply have to implement a DeepClone() method no matter what for every class along the hierarchy? Is the pattern that I am using here incorrect, and there's a better way?
One final note: I would like to avoid reflection if at all possible.
Could use an extension method and do incremental cloning
public static class DeepCopyExt
{
public static T DeepCopy<T>(this T item)
where T : ThingBase, new()
{
var newThing = new T();
item.CopyInto(newThing);
return newThing;
}
}
public abstract class ThingBase
{
public int A { get; set; }
public virtual void CopyInto(ThingBase target)
{
target.A = A;
}
}
public class ThingA : ThingBase
{
}
public class ThingB : ThingA
{
public int B { get; set; }
public override void CopyInto(ThingBase target)
{
var thingB = target as ThingB;
if(thingB == null)
{
throw new ArgumentException("target is not a ThingB");
}
thingB.B = B;
base.CopyInto(thingB);
}
}
class Program
{
static void Main(string[] args)
{
var b = new ThingB
{
A = 1,
B = 3
};
//c is ThingB
var c = b.DeepCopy();
var b1 = new ThingA
{
A = 1,
};
//c1 is ThingA
var c1 = b1.DeepCopy();
Debugger.Break();
}
}
So yes, you have two options:
Either implement DeepClone() each time and in details (list all not-shared properties)
Or use 'quick&dirty' but shared implementation using reflection
Typically you'd need to implement your clone method in the concrete classes. In fact this code you posted won't compile if ImmediateAction is abstract like you said at the top:
return new ImmediateAction(this);
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);
}
}