Reputation: 365
I am trying to insolate classes from others setting or changing data in the class. I have chosen to use an abstract base class called Parent and then two derived abstract classes called DerivedA and DerivedB. Then, using Assembly, I get the derived abstract classes from Parent. Then, I use generics to derive a concrete class, ConcreteGeneric, to hopefully fill in the values of the abstract classes .
The problem I am having is that when I get into my concrete class, I do not have access (see) the parent class members/properties. Maybe this design is all wrong, but this is the ideal way I would like to solve it. Any help would be greatly appreciated... and save the hair that is falling off my head. ;)
Code is attached.
I have documented what I would like in the code. To be able to access and see the public variables in the parent classes.
using System;
using System.Linq;
using System.Reflection;
public abstract class Parent
{
public string Name { get; set; }
public string Comment { get; set; }
}
public abstract class DerivedA : Parent
{
public string DerivedAString { get; set; }
}
public abstract class DerivedB : Parent
{
public string DerivedBString { get; set; }
}
public class DerivedFromA : DerivedA
{
public string DerivedFromAString { get; set; }
}
public class ConcreteGeneric<T> where T : Parent
{
private string _jsonString = "";
public string HeaderString
{
get
{
return _jsonString;
}
set
{
/// I want to be able to see the Derived classes parameters
/// here. Like 'DerivedB.DerivedBString' if T is type DerivedB
_jsonString = value;
}
}
}
public class RunItClass
{
public static void Main()
{
Type[] types = Assembly.GetAssembly(typeof(Parent)).GetTypes();
foreach (Type type in Assembly.GetAssembly(typeof(Parent)).GetTypes()
.Where(myType => myType.IsAbstract && myType.IsSubclassOf(typeof(Parent))))
{
var genType = typeof(ConcreteGeneric<>).MakeGenericType(type);
Type genericType = (Type)genType;
object genericInstance = Activator.CreateInstance(genericType);
dynamic dynamicObj = Convert.ChangeType(genericInstance, genericType);
/// Note that when I drop into the 'set' method on this dynamic object, I cannot see the
/// paramters of the parent class, which is 'DerivedA' on the first item in this loop.
dynamicObj.HeaderString = "Testing";
// Testing here
if (genericType == typeof(ConcreteGeneric<DerivedA>))
{
// ?? I CANNOT see all of the variables in 'DerivedA' ??
ConcreteGeneric<DerivedA> da = (ConcreteGeneric<DerivedA>)genericInstance;
/// I CAN see all of the variables in 'DerivedA' and also 'Parent'. This is what I
/// am after, but I want to be able to use the ConcreteGeneric<![CDATA[>]]> to accomplish this.
/// Please help. :)
DerivedFromA dfa = new DerivedFromA();
Console.WriteLine();
}
}
}
}
Upvotes: 0
Views: 165
Reputation: 42360
The code inside your ConcreteGeneric<T>
class has to work with any T
that you might decide to give it. Since you've constrained T
to Parent
that means you can access any of Parent's
properties.
You can say "I want to be able to see the Derived classes parameters here", but what if you created a ConcreteGeneric<DerivedA>
? Then there wouldn't be any DerivedBString
property there for you to access.
What you might be able to do is to expose your T
directly inside ConcreteGeneric<T>
:
public T Item { get; }
Then you'll be able to cast your genericType
to a ConcreteGeneric<DerivedA>
, and access .Item
:
var concreteDerivedA = (ConcreteGeneric<DerivedA>)genericType;
string s = conceteDerivedA.Item.DerivedAString;
That leaves you with the question of how Item
is set. If you enforce that it must have a parameterless constructor, you can do this:
public class ConcreteGeneric<T> where T : Parent, new()
{
public T Item { get; } = new T();
}
Upvotes: 1