Copying base class in derived class constructor - c#

Is there a way to copy an object fields to a base class in a derived class constructor without having to individually copying every field?
Example:
public class A
{
int prop1 { get; set; }
int prop2 { get; set; }
}
public class B : A
{
public B(A a)
{
//base = a; doesn't work.
base.prop1 = a.prop1;
base.prop2 = a.prop2;
}
}
A a = new A();
B b = new B(a);

public class A
{
public A(A a)
{
prop1 = a.prop1;
prop2 = a.prop2;
}
int prop1 { get; set; }
int prop2 { get; set; }
}
public class B : A
{
public B(A a) : base (a)
{
}
}
A a = new A();
B b = new B(a);
Something like this, although I'm not sure if it is syntactically correct because I didn't compile it. You should use the base keyword after the child class's constructor to pass the values of it's dependencies to the base class.
Edit: But I just realized that you are passing a base class to a child class. And this is a design flaw.

It sounds like you want to add all properties from A to B without having to specify them all separately. If you don't want to have to keep adding new ones to the constructor, you could use reflection to do the work for you.
public B(A a)
{
var bType = this.GetType();
// specify that we're only interested in public properties
var aProps = a.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// iterate through all the public properties in A
foreach (var prop in aProps)
{
// for each A property, set the same B property to its value
bType.GetProperty(prop.Name).SetValue(this, prop.GetValue(a));
}
}
A few notes about this:
The above code sets public instance properties, so you'd need to change your properties in A to be public.
I'd only consider this safe because you know that B contains everything in A (since it is derived from it).
If you only have a few properties, especially if they don't change often, just list them individually... it'll be easier to see exactly what your code is doing.

I can't for the life of me understand why you want to do this
You are passing an instance of Base class into the constructor of a derived class. What are you trying to do?
have you tried this = a instead of base = a?

The members are private, so you can't access them from even a derived class. Even if they were protected, you still couldn't access them on an instance of A from the B class.
In order to do this without reflection, the members will have to be public:
public class A
{
public int prop1 { get; set; }
public int prop2 { get; set; }
}
// Define other methods and classes here
public class B : A
{
public B(A a)
{
//base = a; doesn't work.
base.prop1 = a.prop1;
base.prop2 = a.prop2;
}
}

If you really want to do this and cannot access the properties via inheritance then you can do via reflection like this:
public class Aclass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
public class Bclass : Aclass
{
public Bclass(Aclass aInstance)
{
CopyPropertiesFromAltInstance(aInstance);
}
public void CopyPropertiesFromAltInstance(Aclass aInstance)
{
PropertyInfo[] aProperties = aInstance.GetType().GetProperties();
PropertyInfo[] myProperties = this.GetType().GetProperties();
foreach (PropertyInfo aProperty in aProperties)
{
foreach (PropertyInfo myProperty in myProperties)
{
if (myProperty.Name == aProperty.Name && myProperty.PropertyType == aProperty.PropertyType)
{
myProperty.SetValue(this, aProperty.GetValue(aInstance));
}
}
}
}
}

Related

Pointer from derived class to base class C#

I have 100 classes that will inherit 1 base class. Derived class can have A and B property, just A or B property, or don't have them at all. I need a pointer, from derived class to base class, that will trigger every time I call A or B property from derived classes.
class D1 : Base
{
int A { get; set; } // Point to Base A
}
class D2 : Base
{
int A { get; set; } // Point to Base A
int B { get; set; } // Point to Base B
}
class Base
{
int A => ExampleA();
int B => ExampleB();
int ExampleA()
{
return 10;
}
int ExampleB()
{
return 15;
}
}
static void Main(string[] args)
{
D1 d1 = new D1();
D2 d2 = new D2();
d1.A; //return 10
d2.A; //return 10
d2.B; //return 15
}
If You want to inherit not everything but sometimes A, sometimes B and only sometimes A and B then it looks like You should not inherit from the base class at all. Looks more like You should create 2 interfaces and for example:
class D1 : IBaseA
class D2 : IBaseA, IBaseB
You'll want to make the properties on the base class virtual, so then classes that inherit from it can optionally override the behaivour. (Or you could also make the methods ExampleA and ExampleB virtual and optionally override that behaivour instead), like so:
public class Base
{
// Made these properties get and set, instead of get (read) only
// default values are for illustration purposes
public virtual int A { get; set; } = 1;
public virtual int B { get; set; } = 1;
}
public class Foo : Base
{
public override int A { get; set; } = 10;
}
public class Bar : Base
{
public override int B { get; set; } = 10;
}
Let's test it:
var a = new Foo();
var b = new Bar();
Console.WriteLine($"a.A: {a.A}, a.B: {a.B}");
Console.WriteLine($"b.A: {b.A}, b.B: {b.B}");
If you don't specify anything, Foo and Bar will implicitly have A and B with the same visibility as A and B in the Base class. You can't change the visiblity of a member of a class "after the fact" (i.e without changing it in the base class), so if only some of your classes should expose A or B you'll want to follow what CherryQuery said in their answer
Actually in Base class you don't need A and B. Subclasses should then look like (assuming ExampleX methods are at least protected):
class D1 : Base
{
public int A => ExampleA(); // note this is get-only property
}

Is order of properties in a class important?

I have the following class:
class Foo
{
public Foo()
{
Console.WriteLine("Foo");
}
public string A { get; set; } = GetStr("A");
public string B { get; set; } = GetStr("B");
public static string GetStr(string str)
{
Console.WriteLine(str);
return str;
}
}
when I create an instance from it, the output is this:
A
B
Foo
if I change the of my properties to:
public string B { get; set; } = GetStr("B");
public string A { get; set; } = GetStr("A");
the output is:
B
A
Foo
My Question is:
Does order of properties in a class important and may effect my program?
Note: I use C# 6.0 new feature: Property initializer More
Field (and property, since C# 6) initializers are run first, in the order in which they are declared, then the constructor is executed.
So yes, the order of the properties affects the order in which they will be initialized; but the constructor will always be executed last.
In my experience (in C#), when using reflection, the order of the fields is returned as they are listed in the class (so it may be important).
For example:
public class TestClass
{
// purposely not in alphabetical order and of different types.
public string C { get; set; }
public int A { get; set; }
public string B { get; set; }
}
and then create an instance and assign values:
TestClass testObject = new TestClass();
// purposely not in same order as in class
testObject.B = "1";
testObject.C = "2";
testObject.A = 3;
and finally loop through properties:
foreach (PropertyInfo prop in typeof(TestClass).GetProperties())
{
Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(testObject, null));
}
prints out the following:
C = 2
A = 3
B = 1
The result is the same order as in the class definition.
Order of properties doesn't matter. Your constructor call the GetStr method which writes the string in console. Because of that order of properties seem change.

Cast one class object to other class object

I have two classes A and B and I want to cast an instance of A to B. What's the best way?
How Can I make a utility class to perform this task?
public class A
{}
public class B
{}
A good place to start is by reviewing the MSDN documentation on Casting and Type Conversions.
As there's no direct relationship between the two classes, you'll need to write a Conversion Operator. For example:
public class A
{
public int AValue { get; set; }
}
public class B
{
public int BValue { get; set; }
public static explicit operator B(A instanceOfA)
{
return new B { BValue = instanceOfA.AValue };
}
}
You could then write:
A instanceOfA = new A { AValue = 7 };
B instanceOfB = (B)instanceOfA;
// Will output "7"
Console.WriteLine(instanceOfB.BValue);
The documentation I've derived this example from is on MSDN, Using Conversion Operators.
If there was a direct relationship between the two classes, for example B derives from A, for example:
public class A
{
public int Value { get; set; }
}
public class B : A
{
public string OtherValueSpecificToB { get; set; }
}
You wouldn't then need any extra code if you wanted to cast from B to A:
B instanceOfB = new B { OtherValueSpecificToB = "b", Value = 3 };
A instanceOfBCastToA = (A)instanceOfB;
// Will output "3";
Console.WriteLine(instanceOfBCastToA.Value);
// Will not compile as when being treated as an "A" there is no "OtherValueSpecificToB" property
Console.WriteLine(instanceOfBCastToA.OtherValueSpecificToB);

How to allow nested class instances modification in PropertyGrid not having access to inspected classes code?

Say we have a simple class model with classes as feilds (inside compiled, not modifiable Dll):
public class SubSubClassTest {
public int Data { get; set; }
}
public class SubClassTest {
public string InnerStr { get; set; }
public int InnerInteger { get; set; }
public SubSubClassTest InnerLoad { get; set; }
public SubClassTest() {
InnerLoad = new SubSubClassTest();
}
}
public class Test {
public string Str { get; set; }
public int Integer { get; set; }
public SubClassTest Load { get; set; }
public Test() {
Load = new SubClassTest();
}
}
And we want to edit it using PropertyGrid.
public partial class ApplicationForm : Form {
public ApplicationForm() {
InitializeComponent();
var test = new Test();
propertyGrid.SelectedObject = test;
}
}
And I do not have abilety to change classes (as I get them from Dll) and they have no [TypeConverter(typeof(ExpandableObjectConverter))] attribute on all members that are classes I get sush picture:
And members that are from my namespace class type are not editable.
If all such members havd [TypeConverter(typeof(ExpandableObjectConverter))] attribute I would have another picture and all would be fine:
I wonder how to make PropertyGrid use PropertyGrid for all nested classes?
You could try changing the TypeConverterAttribute value using PropertyDescriptor and Reflection. I wouldn't recommend to do this but to show that its possible I have added the sample code. I verified with your example and it works. But I cannot assure that it would work in all scenarios. Food for thought...
var test = new Test();
SetTypeConverterAttribute(test);
propertyGrid.SelectedObject = test;
private void SetTypeConverterAttribute(Test test)
{
foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(test))
{
TypeConverterAttribute attribute = item.Attributes[typeof(TypeConverterAttribute)] as TypeConverterAttribute;
if (attribute != null && item.PropertyType == typeof(SubClassTest))
{
FieldInfo field = attribute.GetType().GetField("typeName", BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
field.SetValue(attribute, typeof(ExpandableObjectConverter).FullName);
}
}
}
}
If you have control over the classes, you can create a common base class and decorate this base class with the TypeConverterAttribute. In that case, any property that will reference any instance of this type will use the ExpandableObjectConverter, unless this behavior is overridden by the property (using another TypeConverterAttribute).

C# - How to copy/create an object as a decendent

This is easier to explain with an example. Given these two classes:
public class MyClassA
{
public String Property_A { get; set; }
public String Property_B { get; set; }
public String Property_C { get; set; }
public String Property_D { get; set; }
...
public String Property_Y { get; set; }
}
public class MyClassB: MyClassA
{
public String Property_Z { get; set; }
}
Suppose I have fully created instance of MyClassA (with all properties from A - Y filled in). Then I need to make an instance of MyClassB which is exactly the same as my instance of MyClassA but with Property_Z filled in (with a custom value of course). How can I do this?
Doing this does not work (throws and Invalid Cast Exception):
MyClassB myInstanceB = (myClassB) myInstanceA;
myInstance.Property_Z = myCustomValue;
I have not needed to do anything like this since my C++ days and I am stumped.
Any ideas?
UPDATE: I found a solution to my problem in how I create the instances. It is below. I did not mark it as the answer because it did not exactly fit my question.
The instance you've created is a MyClassA. That is its runtime type, not MyClassB. You cannot cast a MyClassA instance to a MyClassB at runtime because MyClassB is a more specific type than MyClassA.
You need to create a brand-new instance of MyClassB. One way to clean this up is to create a constructor that takes a MyClassA, e.g.
public class MyClassB : MyClassA
{
public MyClassB(MyClassA a, string z)
{
this.PropertyA = a.PropertyA;
this.PropertyB = a.PropertyB;
// etc.
this.PropertyZ = z;
}
public string PropertyZ { get; set; }
}
You can use Reflection to copy base class properties as shown here.
public void Update(MyObject o)
{
MyObject copyObject = ...
Type type = o.GetType();
while (type != null)
{
UpdateForType(type, o, copyObject);
type = type.BaseType;
}
}
private static void UpdateForType(Type type, MyObject source, MyObject destination)
{
FieldInfo[] myObjectFields = type.GetFields(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo fi in myObjectFields)
{
fi.SetValue(destination, fi.GetValue(source));
}
}
The straightforward answer:
public class MyClassA
{
public String Property_A { get; set; }
public String Property_B { get; set; }
public String Property_C { get; set; }
public String Property_D { get; set; }
...
public String Property_Y { get; set; }
}
public class MyClassB: MyClassA
{
public MyClassB(MyClassA copy)
{
Property_A = copy.PropertyA;
Property_B = copy.PropertyB;
...
}
public String Property_Z { get; set; }
}
Use it like this:
MyClassB o = new MyClassB(instanceOfMyClassA);
o.Property_Z = whatever;
Sounds like you're looking for a free copy constructor. C# doesn't supply one (http://msdn.microsoft.com/en-us/library/ms173116%28VS.80%29.aspx) but you can do it pretty easily with Object.MemberwiseClone or the BinaryFormatter serializer (http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx). Take care to know if you want a shallow copy or deep copy.
You could define an explicit or implicit cast from MyClassA to MyClassB and use the syntax you've provided.
public class MyClassB : MyClassA
{
public String Property_Z { get; set; }
public static explicit operator MyClassB(MyClassA a)
{
MyClassB b = new MyClassB();
b.Property_A = a.Property_A;
/* ... */
b.Property_Y = a.Property_Y;
return b;
}
}
What about:
Create a base class that implements IClonable and has all the string properties A to D, and Z.
Create instance of this class for MyClassA.
Create instance of MyClassB by cloning MyClassA.
Set property Z in MyClassB.
Here is what I ended up doing:
I made my method that creates and sets up all the properties (A-Y) that uses type parameters. It looks like this:
public T MakeAMyClass<T>(AnotherClass
where T: MyClassA : new()
{
T returnValue = new T();
T.Property_A = somethingToSetFrom.MakeAPropertyA();
// Fill in the rest of the properties
}
Because a type parameter can be a type that is descended from the constraint, I am able to pass in MyClassB objects and get them made the same way as myClassA.
Then I can make either one as needed.
MyClassA myInstanceA = MakeAMyClass<MyClassA>(somethingToSetFrom);
MyClassB myInstanceB = MakeAMyClass<MyClassB>(somethingToSetFrom);
myInstanceB.Property_Z = someotherValue;
The lets me avoid having to make a method to copy all the properties from MyClassA to MyClassB.

Categories