Casting to derived class downward - c#

I have a set of classes that derive one from another and the lower level has complete structure of what i need. the data stored and save is the highest level. in the highest level the Type is stored in the object. how can i cast down the highest level to the lowest. the generic see highest and T is highest which isn't helpful.
example :
Head class with couple core methods/fields :
[Serializable()]
public class CSelectionProperties
{
private Dictionary<string, string> lstProperties = new Dictionary<string, string>();
public Dictionary<string, string> getProperties { get { return lstProperties; } }
private Type objectType = null;
public Type ObjectType { get { return objectType; } set { objectType = value; } }
internal string FindProperty(string sProperty)
{
return FindProperty(sProperty, null);
}
internal string FindProperty(string sProperty, string sNullValue)
{
string sValue = sNullValue;
lstProperties.TryGetValue(sProperty, out sValue);
}
}
here an example of one of the many derived class :
[Serializable()]
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public double getAirVolume()
{
return Convert.ToDouble(FindProperty("INCFMValue", "0"));
}
}
Now all object using these property have the variable as CSelectionProperties so we can reuse everywhere same format.
When a class such as CFilterSelectionProperties gets created the Type get stored into the CSelectionProperties.ObjectTypeas a Type now another project receive a collection of CSelectionProperties and to properly read them i need to cast them as the proper type.
Right now i am going the old way
If(item is CFilterSelectionProperties)
{
RunDataAnalysis(item as CFilterSelectionProperties);
}
Else If (item is ...)
{
RunDataAnalysis(item as ...);
}
i use reflection and i stumble upon a case where i need the actual original class to loop the methods and retrieve some data. is there any way ?
Also some report will need to be open but again i have 4 class that derive from 1 single class that derive from CSelectionProperties at which point i don't have access to anything at all. I'm just trying to get away from If/Else which works fine.
As side note i tried going with and Activator but i can only find how to recreate a class as child type.
CFilterSelectionProperties oItem = new CFilterSelectionProperties();
MyObject.SelectionProperties = Activator.CreateInstance(oItem.ObjectType) as CSelectionProperties;

Not exactly sure if this is what you need but you can have a base class that "knows" the derived type:
class MyBase<T> {}
class A : MyBase<A> {}
class B : MyBase<B> {}
this way you can do this:
void Foo(MyBase<T> baseObj)
{
T derived = (T)(object)baseObj;
// use derived in a strongly-typed manner
}

Without knowing what RunDataAnalysis does it sounds like you can use virtual (or abstract) methods/properties in the base class that are overloaded in the derived classes. Then when you call those methods/properties in RunDataAnalysis you will be using the most derived version without having to cast the variable.
For example:
public class CSelectionProperties
{
... existing stuff
public virtual DataSet GetData(.. some parameters ...)
{
.. do stuff common to ALL subtypes
}
}
and
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public override DAtaSet GetData(... some parameters ...)
{
... do stuff common to THIS type and subtypes
}
}

Related

Downcasting baseclass into derived generic type C#

I am struggling with an issue related with conversion between generic, possibly it's an easy one.
Basically I want to create a list of base class and add into it multiple classes.
public interface IQueryEngineDependency
{
public IEnumerable<QueryDependencyDetail> GetDependencies<>();
}
public abstract class QueryDependencyDetail
{
public int Order { get; set; }
}
public class QueryDependencyDetail<TEntity, TKey> : QueryDependencyDetail
where TEntity : BaseEntity<TKey>
{
public virtual Func<TEntity, object> Key { get; set; }
public IQueryable<TEntity> Data { get; set; }
public Func<TEntity, object> JoinKey { get; set; }
public Expression<Func<TEntity, bool>> WhereClause { get; set; }
}
Problem
I have a class, per example, that implements the interface shown above but I am figuring it out the right way to implement this.
public class TestQueryDependency : IQueryEngineDependency
{
public IEnumerable<QueryDependencyDetail> GetDependencies()
{
var dependencies = new List<QueryDependencyDetail>
{
new QueryDependencyDetail<Tasks, long>
{
Order = 1,
Data = null // just to simplify
}
};
return dependencies;
}
}
If I call the method GetDependencies somewhere in the code how can I make the downcasting to access the generic type fields? I mean I will get the instances of QueryDependencyDetail type. Then is it possible to convert it to QueryDependencyDetail<TEntity, TKey>?
Or is there another way to do this?
EDIT
var testDep = new TestQueryDependency();
var dependencies = testDep.GetDependencies();
Remember that dependencies may have up to 20 different instances in my particular implementation.
How can I access the Data field, per example? (Just a simple scenario)
var first = dependencies.FirstOrDefault()?.Data; ?????
I will need this to perform dynamic queries using LINQ.
Thanks in advance.
I am not sure what you are trying to accomplish.
What if you put the generic arguments on the engine interface?
public interface IQueryEngineDependency<TEntity,TKey> where TEntity : BaseEntity<TKey> {
public IEnumerable<QueryDependencyDetail<TEntity,TKey>> GetDependencies();
}
Then you can create a test engine:
public class TestQueryDependency : IQueryEngineDependency<Tasks,long> {
public IEnumerable<QueryDependencyDetail<Tasks,long >> GetDependencies() {
var dependencies = new[] {
new QueryDependencyDetail<Tasks, long> {
Order = 1,
Data = null // just to simplify
}
};
return dependencies;
}
}
You should be able to just cast it, i.e. (QueryDependencyDetail<TEntity, TKey>) myObject
However, you must make sure that the type actually match the real object. Lets take a simplified example:
public class A { }
public class B<T> : A { }
public static B<T> Test<T>(A a) => (B<T>)a;
and
var a = new B<int>();
var b1 = Test<int>(a); // works since a is of type of B<int>
var b2 = Test<string>(a); // Will throw invalid cast exception since a is not of type B<string>
You can also test the type:
if(a is B<int> b)
The problem here is that you have to know the actual type of the object. You cannot just cast a to B<T> without somewhere declaring what T actually is.
The solution I have used for these kind of problems is to avoid anything that needs to know the generic type. Make sure the interface or base class contain all methods you ever need when interacting with the object. This can be a bit complicated when multiple classes are involved, but it is usually possible.
edit:
A third option could be to use reflection. This can allow you to inspect the actual types of the generic type parameters. It may allow for things like creating another object with the same generic type parameter. The downside is that using reflection can be quite cumbersome and may be error prone and slow.

C# - list of subclass Types

I'd like to have a List of Class Types (not a list of Class instances) where each member of the List is a Subclass of MyClass.
For example, i can do this:
List<System.Type> myList;
myList.Add(typeof(mySubClass));
but i'd like to restrict the list to only accept subclasses of MyClass.
This is distinct from questions like this.
Ideally i'd like to avoid linq, as it's currently unused in my project.
Servy is right in his comment, and Lee in his: it's much more preferable to compose than inherit. So this is a good option:
public class ListOfTypes<T>
{
private List<Type> _types = new List<Type>();
public void Add<U>() where U : T
{
_types.Add(typeof(U));
}
}
Usage:
var x = new ListOfTypes<SuperClass>();
x.Add<MySubClass>()
Note that you can make this class implement an interface like IReadOnlyList<Type> if you want to give other code read access to the contained Types without other code having to depend on this class.
But if you want to inherit anyway, you could create your own class that inherits from List, then add your own generic Add method like this:
public class ListOfTypes<T> : List<Type>
{
public void Add<U>() where U : T
{
Add(typeof(U));
}
}
Just be aware of what Lee said: with this second version you can still Add(typeof(Foo)).
You should derive a list class from List and override the Add method to perform the type checking that you need. I'm not aware of a way in .NET to do that automatically.
Something like this could work:
public class SubTypeList : List<System.Type>
{
public System.Type BaseType { get; set; }
public SubTypeList()
: this(typeof(System.Object))
{
}
public SubTypeList(System.Type baseType)
{
BaseType = BaseType;
}
public new void Add(System.Type item)
{
if (item.IsSubclassOf(BaseType) == true)
{
base.Add(item);
}
else
{
// handle error condition where it's not a subtype... perhaps throw an exception if
}
}
}
You would need to update the other methods that add/update items to the list (index setter, AddRange, Insert, etc)

Serialize Class obtained using Reflection to XML

I have a file that looks like the following:
public abstract class TestStep
{
public abstract bool DoWork();
public abstract List<TestStep> PrerequisiteSteps { get; set; }
public abstract string DisplayForm { get; }
}
class TestFunctions
{
public class A : TestStep
{
public override string DisplayForm { get { return "MainForm; } }
// remaining implementation goes here...
}
public class B : TestStep { // some implementation }
public class C : TestStep { // some implementation }
public static void NextStep() { }
}
I'd like to serialize the classes A, B, and C to an XML file. I can manually add instances of these classes to a List<TestStep> object and pass that to an XML serializer, but I'd like to programmatically accomplish this because I might add or remove classes in TestFunctions in the future. As a result, I've found that I can use reflection to get an array of the functions:
Type type = (typeof(TestEngineFunctions));
Type[] testEngineFunctions = type.GetNestedTypes(BindingFlags.Public);
However I'm not sure how to proceed from here. I have access to the name of the functions, I can get their properties as well, but ultimately I don't have an actual object to serialize.
Am I on the right track or is there another method better suited for this?
You can get a new instance of the objects like this:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
Since you may not know the ObjectType before run time you could use the dynamic type and don't cast:
dynamic instance = Activator.CreateInstance(objectType);
However, if you attempt to serialize right after you instantiate you'll just get the default values of the object in your XML.

Implement copy/deepcopy on multiple base classes

not sure if this maybe is a codeReview post but here we go:
My goal is to re-implement the way objects are copied within our application. We have multiple base classes:
CoreList<T> // for all list classes
BasicReference // for all reference classes
CoreObject // for all "normal" domain objects
All classes inherit from these base classes. Right now the copy method is implemented on the CoreObject class and will go through the object tree via reflection, looking at each property type and select the correct way to copy the type and finally returning always CoreObject.
There are some problems which I don't like about that approach, which is why I would like to change it:
After copying an domain object you always have to cast it "back" to the original type, for example: Animal = animal.Copy() as Animal;
All logic to copy each type is within the CoreObject class even though it should not know about other base classes.
So my first attempt was to introduce a interface:
public interface IObjectCopy<out T>
{
T Copy();
}
Which then should be implemented on all base classes. Then every class is responsible for the way it is copied. For example (pseudo code):
public class CoreObject : IObjectCopy<CoreObject>
{
public virtual GerCoreObject Copy()
{
foreach (var prop in properties)
{
if (prop.IsNoSimpleType)
{
(prop as IObjectCopy).Copy()
}
}
}
That solves the copy-responsibility problem, in addition inherited classes can take care of the copy logic themselves.
Unfortunately that does not solve the return type, I still have to cast it to the correct type. I did not think of a better solution to solve this. Any ideas?
This problem could be solved in OO using covariant return types. Unfortunately C# does not support covariant return types like Java and C++, requiring it to always break type safety.
Without breaking type safety (casting) in C# this is unfortunately not possible.
Here are two possible options:
//explicit interface implementation
public class Animal : CoreObject, IObjectCopy<Animal>
{
Animal IObjectCopy<Animal>.Copy()
{
return (Animal) base.Copy();
}
}
//does not require an explicit cast
IObjectCopy<Animal> animalCopy = myAnimal;
Animal copiedAnimal = animalCopy.Copy();
//second option: shadow the original method and cast inside the object
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return (Animal) base.Copy();
}
}
Animal copy = myAnimal.Copy();
Another option using bounded quantification:
public class CoreObject : IObjectCopy<CoreObject>
{
public CoreObject Copy()
{
return Copy<CoreObject>();
}
protected T Copy<T>()
where T : CoreObject, new()
{
T t = new T();
//implement copy logic:
return t;
}
}
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return Copy<Animal>();
}
}
If I understood it correctly, you need Curiously recurring template pattern
public class BaseClass<T> where T : BaseClass<T>
{
public virtual T Clone()
{
// Perform cloning with reflection.
return clone as T;
}
}
Then you just define your class as:
public class EndObject : BaseClass<EndObject>
{
}
EndObject e;
e.Clone() // Will return EndObject type

Really bizarre C# generics question

This code compiles but looks very strange.
I have a typical and simple parent/child relationship here which is implemented using generics in a very strange way.
But I can't seem to find any other way of doing it.
class SampleObject<T> //I don't want to make this a generic but am forced to
{
//The SampleContainer this object is in
//This must be located in this base class
public SampleContainer<T> Parent { get; set; }
}
class SpecificObject : SampleObject<SpecificObject>
//SampleObject<SpecificObject> !!? This is the bizzare bit
//It seems really strange but necessary for compilation to work
{
}
//A class to contain a List of objects derived from SampleObjects
class SampleContainer<T>
{
public List<T> List;
}
class Start
{
public void Test()
{
SampleContainer<SpecificObject> container = new SampleContainer<SpecificObject>();
SpecificObject o = new SpecificObject(); //create an object
container.List.Add(o); //add it to the list
o.Parent = container; //set its parent
}
}
Can this code be simplified?
This seems to work without the type.
Is this what you were looking for?
class SampleObject //I don't want to make this a generic but am forced to
{
//The SampleContainer this object is in
//This must be located in this base class
public SampleContainer<SampleObject> Parent;//{ get; set; }
}
class SpecificObject : SampleObject
//SampleObject<SpecificObject> !!? This is the bizzare bit
//It seems really strange but necessary for compilation to work
{
}
//A class to contain a List of objects derived from SampleObjects
class SampleContainer<T>
{
public List<T> List;
}
class Start
{
public void Test()
{
SampleContainer<SampleObject> container = new SampleContainer<SampleObject>();
SpecificObject o = new SpecificObject(); //create an object
container.List.Add(o); //add it to the list
o.Parent = container; //set its parent
}
}
In the MSDN documentation, it states that:
When deriving from a generic base
class, you must provide a type
argument instead of the base-class's
generic type parameter:
public class BaseClass<T>
{...}
public class SubClass : BaseClass<int>
{...}
It's probably a constraint that the C# designers set up in the compiler. They require that a derived type must specify the type of the generic argument at compile time. I'm not quite sure why.
Generics can create some unwieldy class hierarchies. However, the syntax for SpecificObject : SampleObject does make sense, since you're stating that the object has a parent relationship. The only other way I could see you do this, would be to split out the hierarchy with an interface. It doesn't buy much, but it may help clarify the intent.
interface IHasParent<T>
{
T Parent { get; set; }
}
public class SpecificObject : IHasParent<SpecificObject>
{
public SpecificObject Parent { get; set; }
}
If you're concerned about how verbose your collection is, you can tame the angle brackets a bit by using:
public SpecificObjectContainer : Container<SpecificObject>
{
}

Categories

Resources