Initialization of Extended class? - c#

I am getting object of a class AAA from somewhere and I want to add more information in that object. So, I am creating a new class BBB which is derived from AAA. The class BBB has additional field dictionary. I am populating this dictionary in derived class constructor which is taking the Class AAA object and array of item which I want to use as keys of dictionary and values of this dictionary are elements of a field of object of class AAA. I tried to create similar scenario in blow example code:
void Main(){
A obj = new A () ;
obj.prop1 = new int [] {5 ,10, 15} ;
obj.prop2 = "Hello" ;
obj.prop3 = "World" ;
// obj.Dump () ;
B obj2 = new B (new int [] {1,2,3}, obj) ;
// obj2.Dump () ;
}
// Define other methods and classes here
public class A {
public int [] prop1 ;
public string prop2 ;
public string prop3 ;
}
public class B : A {
public Dictionary <int, int> prop4 ;
public B (int [] keys, A a) {
prop4 = new Dictionary <int, int> () ;
if (keys.Length == a.prop1.Length ) {
for (int i = 0 ; i < keys.Length ; i++ ) {
prop4.Add (keys[i], a.prop1[i]) ;
}
// is there a way to obsolete below lines of code???
this.prop1 = a.prop1 ;
this.prop2 = a.prop2 ;
this.prop3 = a.prop3 ;
}
else {
throw new Exception ("something wrong") ;
}
}
}
In derived class constructor, I am filling the properties manually and I do not want to do it. Is there another way to do it. I have more than 20 properties in my actual class.

Can't do what you're asking but I'd suggest creating a copy constructor for class A and using it with your class B constructor:
// Define other methods and classes here
public class A
{
public int[] prop1;
public string prop2;
public string prop3;
public A()
{
}
public A(A orig)
{
prop1 = orig.prop1;
prop2 = orig.prop2;
prop3 = orig.prop3;
}
}
public class B : A
{
public Dictionary<int, int> prop4;
public B(int[] keys, A a) : base( a )
{
prop4 = new Dictionary<int, int>();
if (keys.Length == prop1.Length)
{
for (int i = 0; i < keys.Length; i++)
{
prop4.Add(keys[i], prop1[i]);
}
}
else
{
throw new Exception("something wrong");
}
}
}

What you are implementing here is very similar to a copy constructor. Doing it by hand is the only way I'm afraid!
My advice is to use Properties in your class A definition and override the properties for your class B implementation:
// Define other methods and classes here
public class A
{
public virtual int[] prop1 { get; set; }
public virtual string prop2 { get; set; }
public virtual string prop3 { get; set; }
}
public class B : A
{
public Dictionary<int, int> prop4;
public override int[] prop1
{
get
{
return m_WrappedAInstance.prop1;
}
set
{
m_WrappedAInstance.prop1 = value;
}
}
public override string prop2
{
get
{
return m_WrappedAInstance.prop2;
}
set
{
m_WrappedAInstance.prop2 = value;
}
}
public override string prop3
{
get
{
return m_WrappedAInstance.prop3;
}
set
{
m_WrappedAInstance.prop3 = value;
}
}
A m_WrappedAInstance = null;
public B(int[] keys, A a)
{
m_WrappedAInstance = a;
prop4 = new Dictionary<int, int>();
if (keys.Length == a.prop1.Length)
{
for (int i = 0; i < keys.Length; i++)
{
prop4.Add(keys[i], a.prop1[i]);
}
}
else
{
throw new Exception("something wrong");
}
}
}
Functionally, this will act similarly. The only downside is that your wrapped class A instance can no longer be changed independently of your class B instance. Is this a requirement?

Instance of B (which you are constructing) and instance of A (which you are passing to constructor of B) are not related - they hold different data, they sit on different memory addresses. The only way to update properties/fields of B instance from values of passed A is copying.

Hmmmmmmm... Its a bit unclear and confusing what you up to but take a look at this:
Maybe its not related to what you need but at least it might give you an idea.
This is how you can create a dictionary from all the properties of a type.
public static Dictionary<string, object> DictionaryFromType(object atype)
{
if (atype == null) return new Dictionary<string, object>();
Type t = atype.GetType();
PropertyInfo[] props = t.GetProperties();
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (PropertyInfo prp in props)
{
object value = prp.GetValue(atype, new object[]{});
dict.Add(prp.Name, value);
}
return dict;
}
Might help you out. If not let me know to remove this question.

Define an array. Then cast the items in the array to individual properties
In class A
public object[] properties;
public int[] prop1 {
get { return (int[]) properties[0]; }
set { properties[0] = value; } }
public string prop2 {
get { return (string)properties[1]; }
set { properties[1] = value ; } }
Constructor of B
public B (int[] keys, A obj)
{
properties = A.properties;
}

Related

How to convert parent collection object to child collection object without looping in C#?

I have following object structure where B is derived from A and I am getting input as List<A> with lots of records. I want to convert thatList<A> to List<B> with easy steps (without looping). What is the best way to achieve the same.
Note: I don't want to use AutoMapper.
public class A
{
public A() { }
public virtual string Name
{
get;
set;
}
}
public class B : A
{
public B()
: base()
{
}
private string _name;
public override string Name
{
get
{
return _name;
}
set
{
_name = string.Concat("Hello ", base.Name);
}
}
public string Id
{
get { return "101"; }
}
}
You can do this by declaring constructor for class B from class A
in this way:
public B(A a):base()
{
this._name = a.Name;
}
And than do this:
var listA = new List<A> { new A { Name = "John" }, new A { Name = "Peter" }, new A { Name = "Julia" } };
List<B> listB = listA.Select(x=> new B(x)).ToList();
Based on the comments this is the output, though I still don't really understand the point.
List<A> thisIsA = new List<A>();
thisIsA.Add(new B());
List<B> thisIsB = new List<B>();
thisIsB.AddRange(thisIsA.Cast<B>());

C# array of properties

I have several get properties that I would like to be able to loop through like an array of functions. I would like to be able to do something like this
public int prop1 { get; }
public string prop2 { get; }
public int[] prop3 { get; }
public int prop4 { get; }
public string prop5 { get; }
public string prop6 { get; }
Func<var> myProperties = { prop1, prop2, prop3, prop4, prop5, prop6 };
ArrayList myList = new ArrayList();
foreach( var p in myProperties)
{
myList.Add(p);
}
This code is very broken, but I think it conveys the idea of what I would like to be able to do. Anyone know how I can achieve this?
You could use reflection to access the properties within your type:
class MyType
{
public int prop1 { get; }
public string prop2 { get; }
public int[] prop3 { get; }
public int prop4 { get; }
public string prop5 { get; }
public string prop6 { get; }
public List<string> GetAllPropertyValues()
{
List<string> values = new List<string>();
foreach (var pi in typeof(MyType).GetProperties())
{
values.Add(pi.GetValue(this, null).ToString());
}
return values;
}
}
Note that reflection is slow and you shouldn’t use this if there is a better way. For example when you know that there are only 6 properties, just go through them individually.
If you know all the properties you want to loop through already, then you can try this
List<Reflection.PropertyInfo> myProperties = new List()<object>
{
typeof(SomeType).GetProperty("prop1"),
typeof(SomeType).GetProperty("prop2"),
typeof(SomeType).GetProperty("prop3"),
typeof(SomeType).GetProperty("prop4"),
typeof(SomeType).GetProperty("prop5"),
typeof(SomeType).GetProperty("prop6")
};
foreach(var p in myProperties)
{
var value = p.GetValue(someObject, new object[0]);
myList.Add(p);
}
If not, you can use something like this:
var myProperties =
from pi in someObject.GetType().GetProperties()
select new
{
pi.Name,
Value = pi.GetValue(object, new object[0])
};
foreach(var p in myProperties)
{
myList.Add(p.Value);
}
You can try to use GetProperties
GetProperties Documentation
Example:
PropertyInfo[] myPropertyInfo;
// Get the properties of 'Type' class object.
myPropertyInfo = Type.GetType("System.Type").GetProperties();
Console.WriteLine("Properties of System.Type are:");
for (int i = 0; i < myPropertyInfo.Length; i++)
{
Console.WriteLine(myPropertyInfo[i].ToString());
}
Further Info:
The example for GetProperties with flags is really nice, and it can be useful for you if you want to access to a specific subset of Properties (Like only the Public Ones)
The code is not so far from working. The myProperties variable should be an array, and you need to create functions that read from the properties. (The property getter is actually implemented as a function, but you can't call it as a function or get a reference to it.) Then you use them by calling them.
public class MyClass {
public int prop1 { get; set; }
public string prop2 { get; set; }
public int[] prop3 { get; set; }
public int prop4 { get; set; }
public string prop5 { get; set; }
public string prop6 { get; set; }
public ArrayList GetProperties() {
Func<object>[] myProperties = {
() => prop1, () => prop2, () => prop3,
() => prop4, () => prop5, () => prop6
};
ArrayList myList = new ArrayList();
foreach (var p in myProperties) {
myList.Add(p());
}
return myList;
}
}
If you're needing your Properties in an Array, because you're needing to (as I did) Set and/or Get several related (and same-Typed) Properties, here's what you can do. I know Reflection is "'slow'", but for my use cases, the duplicate code (and therefore error chance) reduction benefits far outweigh any "'slowness'" (which are insignificant) due to Reflection. This does not handle Indexed Properties, but a version to so can easily be created from this.
`
public class MyClass
{
private string[] myBoolPropertyNames =
{
nameof(MyBool1Property),
nameof(MyBool2Property)
}; // MyBoolPropertyNames =
private MyClass()
{
foreach (var propertyName in myBoolPropertyNames)
{
ReflectionHelper.SetPropertyValue
(
parentObject: this,
propertyName: propertyName,
untypedPropertyValue: true
); // SetPropertyValue
} // foreach (var propertyName in myBoolPropertyNames)
foreach (var propertyName in myBoolPropertyNames)
{
bool boolPropertyValue = ReflectionHelper.GetPropertyValue<bool>
(
parentObject: this,
propertyName: propertyName
); // SetPropertyValue
Console.WriteLine($"Property '{propertyName}' value: {boolPropertyValue}");
} // foreach (var propertyName in myBoolPropertyNames)
}
public bool MyBool1Property { get; set; }
public bool MyBool2Property { get; set; }
} // MyClass
`
`
public class ReflectionHelper
{
public static PropertyType GetPropertyValue<PropertyType>
(
object parentObject,
string propertyName
)
{
if (parentObject == null)
{
throw new ArgumentException
(
$"Missing '{nameof(parentObject)}'."
);
} // if (parentObject == null)
PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
if (propertyInfo == null)
{
throw new ArgumentException
(
"No PropertyInfo found for Property: " + propertyName
);
} // if (propertyInfo == null)
object untypedPropertyValue = propertyInfo.GetValue(obj: parentObject);
Type propertyType =
(
Nullable.GetUnderlyingType(propertyInfo.PropertyType)
?? propertyInfo.PropertyType
); // propertyType =
object typedPropertyValue =
(
(untypedPropertyValue == null)
? null
: Convert.ChangeType(untypedPropertyValue, propertyType)
); // typedPropertyValue =
return (PropertyType)typedPropertyValue;
} // GetPropertyValue
public static void SetPropertyValue
(
object parentObject,
string propertyName,
object untypedPropertyValue
)
{
if (parentObject == null)
{
throw new ArgumentException
(
$"Missing '{nameof(parentObject)}'."
);
} // if (parentObject == null)
PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
if (propertyInfo == null)
{
throw new ArgumentException
(
"No PropertyInfo found for Property: " + propertyName
);
} // if (propertyInfo == null)
Type propertyType =
(
Nullable.GetUnderlyingType(propertyInfo.PropertyType)
?? propertyInfo.PropertyType
); // propertyType =
object typedPropertyValue =
(
(untypedPropertyValue == null)
? null
: Convert.ChangeType(untypedPropertyValue, propertyType)
); // typedPropertyValue =
propertyInfo.SetValue
(
obj: parentObject,
value: typedPropertyValue
); // propertyInfo.SetValue
} // SetPropertyValue
} // ReflectionHelper
`
You can use an array buffer and get all prop from it. in this way you can get and set very fast:
public object[] buf = new object[5];
public int prop1 { get => buf[0]; }
public string prop2 { get => buf[1]; }
public int[] prop3 { get => buf[2]; }
public int prop4 { get => buf[3]; }
public string prop5 { get => buf[4]; }
public string prop6 { get => buf[5]; }
Now can access all prop with buf:
foreach (var item in buf) {
myList.Add(item);
}
Or direct access :
buf[1] = 10;
x = buf[1];

Assign Properties from Method

I have two class, base and inherited class like these
public class A
{
public string Prop1 { get; set; }
}
public class B : A
{
public string Prop2 { get; set; }
}
Now i have a method which return class A after populating properties values
public A GetPopulatedValues()
{
//code to populate values here
}
Now my question is, how to assign all the property values at once?
This works
public void Init()
{
var obj = new B();
obj.Prop1 = GetPopulatedValues().Prop1;
}
But i want something like this
public void Init()
{
var obj = new B();
obj = GetPopulatedValues();
}
Any ideas?
Create a constructor:
public Foo(string prop1, string prop2)
{
Prop1 = prop1;
Prop2 = prop2;
}
Or a copy constructor:
public Foo(Foo other)
{
Prop1 = other.Prop1;
Prop2 = other.Prop2;
}
Or use an object initializer:
var foo = new Foo { Prop1 = "Hello", Prop2 = "World" };
But as #RudiVisser says, you'll actually want to fix this in the GetPopulatedValues() method, by supplying a reference to the object you want to populate:
static class FooPopulator
{
public static void PopulateValues(Foo foo)
{
foo.Prop1 = "Hello";
foo.Prop2 = "World";
}
}
var foo = new Foo();
FooPopulator.PopulateValues(foo);
Now your foo object is usable and populatable, without having to alter the Foo class. Added bonus: when you add a property to populate (say Prop3), you will only have to alter the PopulateValues() method.
In your code you also have to do that, but then you'd need to also add the Prop3 assignment, which, if forgotten, will cause bugs.
I agree with #CodeCaster that this should probably be done with a constructor modification, but just to provide another alternative - why not make your GetPopulatedValues method accept an instance of A, and populate the values directly.
public void GetPopulatedValues(A instance)
{
instance.Prop1 = (whatever);
}
public void Init()
{
var obj = new B();
GetPopulatedValues(obj);
}

Should data classes which are passed by a webservice be attributes with [Serializable]

I want to transfer some data classes via Webservice:
public class MyClass
{
public int Int { get; set; }
public MyClass(int v)
{
Int = v;
}
private MyClass()
{
}
}
public enum MyEnum
{
One = 7,
Two = 13,
Three = 15
}
public class TestDataClass
{
private int _someInt;
public List<MyClass> Values { get; set; }
public int SomeInt
{
get
{
return _someInt + 10;
}
set { _someInt = value; }
}
public TestDataClass(int someInt)
{
SomeInt = someInt;
Values = new List<MyClass>();
for (int i = 0; i < 10; i++)
{
Values.Add(new MyClass(i));
}
}
private TestDataClass() {}
}
TestDataClass is the class beening passed, what should be attributed with serializable?
Thanks, Alex.
If you want to use the (old) ASMX style webservice: Yes.
When using WCF: No, use [DataContract] instead.
In both cases, you need attributes for the main class and for any embedded type that is not already Serializable or a 'known type'.

Accessing a property of derived class from the base class in C#

In C#, what is the best way to access a property of the derived class when the generic list contains just the base class.
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
}
public class ClassB: BaseClass
{
public object PropertyB { get; set; }
}
public class BaseClass
{
}
public void Main
{
List<BaseClass> MyList = new List<BaseClass>();
ClassA a = new ClassA();
ClassB b = new ClassB();
MyList.Add(a);
MyList.Add(b);
for(int i = 0; i < MyList.Count; i++)
{
//I would like to access PropertyA abd PropertyB from the derived classes
}
}
Certainly you can downcast, like so:
for (int i = 0; i < MyList.Count; i++)
{
if (MyList[i] is ClassA)
{
var a = ((ClassA)MyList[i]).PropertyA;
// do stuff with a
}
if (MyList[i] is ClassB)
{
var b = ((ClassB)MyList[i]).PropertyB;
// do stuff with b
}
}
... However, you should take another look at what you're trying to accomplish. If you have common code that needs to get to properties of ClassA and ClassB, then you may be better off wrapping access to those properties up into a shared, virtual property or method in the ancestor class.
Something like:
public class BaseClass
{
public virtual void DoStuff() { }
}
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
public override void DoStuff()
{
// do stuff with PropertyA
}
}
public class ClassB : BaseClass
{
public object PropertyB { get; set; }
public override void DoStuff()
{
// do stuff with PropertyB
}
}
Further to TimJ's answer, you can write one extension method that will work for all types:
public static IEnumerable<T> OfType<T>(this IEnumerable list)
{
foreach (var obj in list)
{
if (obj is T)
yield return (T)obj;
}
}
Or if you have Linq, that function is in the namespace System.Linq.
BaseClass o = MyList[i];
if (o is ClassB)
{
object k = ((ClassB)o).PropertyB;
}
if (o is ClassA))
{
object j = ((ClassA)o).PropertyA;
}
If you are doing this a lot, another option would be to create an extension method on the list to give you back the correctly typed enumeration. i.e.
public static class MyBaseListExtensions
{
public static IEnumerable<ClassA> GetAllAs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassA)
{
yield return (ClassA)obj;
}
}
}
public static IEnumerable<ClassB> GetAllbs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassB)
{
yield return (ClassB)obj;
}
}
}
}
Then you could use it like....
private void button1_Click(object sender, EventArgs e)
{
ClassA a1 = new ClassA() { PropertyA = "Tim" };
ClassA a2 = new ClassA() { PropertyA = "Pip" };
ClassB b1 = new ClassB() { PropertyB = "Alex" };
ClassB b2 = new ClassB() { PropertyB = "Rachel" };
List<MyBaseClass> list = new List<MyBaseClass>();
list.Add(a1);
list.Add(a2);
list.Add(b1);
list.Add(b2);
foreach (var a in list.GetAllAs())
{
listBox1.Items.Add(a.PropertyA);
}
foreach (var b in list.GetAllbs())
{
listBox2.Items.Add(b.PropertyB);
}
}
The whole premise doesn't make sense - what would PropertyB be for the a instance?
You can do this if you do manual runtime type checking (inst is Foo), and then cast to the type with the property you want.
You might have some issues with Generics and subclasses (in which case you should go back to System.Collections.ArrayList), but you have to cast the BaseClass to the subclass you wish to use. If you use the 'as' directory, it will succeed if the BaseClass can be casted to the subclass, or it will be null if it cannot be cast. It would look something like:
for(int i = 0; i < MyList.Count; i++)
{
BaseClass bc = MyList[i];
ClassA a = bc as ClassA;
ClassB b = bc as ClassB;
bc.BaseClassMethod();
if (a != null) {
a.PropertyA;
}
if (b != null) {
b.PropertyB;
}
}
Also, I should mention that this smells a bit bad. This is the kind of code that indicates a poorly structured object heirarchy. In general, if you can't say a IS A BaseClass, your design is probably wrong. But, hope that helps!
You would need to have the properties be declared as virtual on the base class and then override them in the derived class.
Ex:
public class ClassA : BaseClass
{
public override object PropertyA { get; set; }
}
public class ClassB: BaseClass
{
public override object PropertyB { get; set; }
}
public class BaseClass
{
public virtual object PropertyA { get; set; }
public virtual object PropertyB { get; set; }
}
public void Main
{
List<BaseClass> MyList = new List<BaseClass>();
ClassA a = new ClassA();
ClassB b = new ClassB();
MyList.Add(a);
MyList.Add(b);
for(int i = 0; i < MyList.Count; i++)
{
// Do something here with the Property
MyList[i].PropertyA;
MyList[i].PropertyB;
}
}
You would either need to implement the property in the base class to return a default value (such as null) or to make it abstract and force all the derived classes to implement both properties.
You should also note that you could return different things for say PropertyA by overrideing it in both derived classes and returning different values.

Categories