List<Parent> holding Child element without losing properties C# - c#

I have these classes
class Start
{
public List<Base> list { get; set; }
public Start()
{
list = new List<Base>();
}
}
public abstract class Base
{
public int a { get; set; }
}
class B : Base
{
public int b;
public B(int a, int b) { this.a = a; this.b = b; }
}
class C : Base
{
public int c;
public C(int a, int c) { this.a = a; this.c = c; }
}
I want list property of class Start to hold instances of class B or instances of class C (not both together, but it may hold the same type of any of B or C)
If possible, I don't want to use Generics
In C#, This is possible:
List<Object> lst = new List<Object>();
lst.Add(1);
list.Add("Text");
Console.WriteLine("{0} {1}", lst[0], lst[1]);
I don't understand why I can't make a similar behavior here:
Start s = new Start();
B b = new B(1, 2);
s.list.Add(b);
Console.WriteLine(s.list[0].a); //works
Console.WriteLine(s.list[0].b); //doesn't work

The difference between the two snippets is that in the first one you are not accessing any type-specific information (fields/properties/methods), i.e. something like the following will not compile too:
List<Object> lst = new List<Object>();
lst.Add(1);
list.Add("Text");
// will not compile despite string having Length property:
Console.WriteLine("{0} {1}", lst[0], lst[1].Length);
a is common property declared in Base class, so it is available for every child of Base, if you want to access child specific properties you need to type test/cast :
Start s = new Start();
B b = new B(1, 2);
s.list.Add(b);
Console.WriteLine(s.list[0].a); //works
if(s.list[0] is B b)
{
Console.WriteLine(b.b);
}
or make Start generic:
class Start<T> where T: Base
{
public List<T> list { get; set; }
public Start()
{
list = new List<T>();
}
}
var s = new Start<B>();
s.list.Add(new B(1, 2));
Console.WriteLine(s.list[0].b);
P.S.
Note that overriding ToString in Base, B and A will make Console.WriteLine("{0}", s.list[0]); "work":
class B : Base
{
// ...
public override string ToString() => return $"B(A: {a} B: {b})";
}
class C : Base
{
// ...
public override string ToString() => return $"C(A: {a} B: {c})";
}
Start s = new Start();
B b = new B(1, 2);
s.list.Add(b);
s.list.Add(new C(4, 2));
Console.WriteLine("{0} {1}", s.list[0], s.list[1]); // prints "B(A: 1 B: 2) C(A: 4 B: 2)"
So possibly you can introduce some method in Base which will allow you to use List<Base> (hard to tell without knowing actual use case).

The List<Object> example is possible because both int and string inherit from Object, which provides a ToString() method that is called implicitly on the line that writes the output. That is, no members of either the int or string types are used in that example that are specific to their own types.
You might accomplish what you need without generics by adding an interface that both B and C can implement, since both the b and c properties are compatible (they are both ints). However, this is clearly a contrived example, and I expect the real code is more complicated. In that case, generics are likely your best option.

because all Base objects dont have 'b' fields
you need to test to see if list[0] is an instance of 'B' and then cast it to a B
if (list[0] is B )
{
Console.WriteLine(((B)(list[0]).b);
}

Based on the comments underneath the question, perhaps a combination of both a non-generic interface and a generic Start class could work in this scenario.
The non-generic base interface for the generic Start class would declare a get-only List property as IReadOnlyList<Base>. IReadOnlyList is co-variant, allowing to return different List<T> instances where T is a concrete derived type from Base.
public interface IStart
{
IReadOnlyList<Base> List { get; }
}
The generic Start<TBase> class implements IStart, puts the IStart.List property in an explicit interface declaration and declares its own List property that is typed as List<TBase>.
public class Start<TBase> : IStart where TBase : Base
{
public List<TBase> List { get; set; }
IReadOnlyList<Base> IStart.List => this.List;
public Start()
{
List = new List<TBase>();
}
}
Note that both the explicit interface implementation of IStart.List and Start<TBase>'s own List property return the same List<TBase> instance.
This setup makes the following things possible (or impossible, see the code comments):
var startC = new Start<C>();
startC.List.Add(new C()); // this works, of course it works
startC.List.Add(new B()); // The compiler will NOT allow this
IStart SomeMethodProducingAStart()
{
if (someCondition)
return new Start<B>();
else
return new Start<C>();
}
void SomeMethodConsumingAStart(IStart start)
{
if (start is Start<B> startWithBs)
{
// do stuff with startWithBs...
Console.WriteLine(startWithBs.List[0].a);
Console.WriteLine(startWithBs.List[0].b);
}
else if (start is Start<C> startWithCs)
{
// do stuff with startWithCs...
Console.WriteLine(startWithCs.List[0].a);
Console.WriteLine(startWithCs.List[0].c);
}
// if you don't care about the members specific to either B or C,
// just do this
Console.WriteLine(start.List[0].a);
// since start can be any Start<T>
// the following is denied by the compiler
// simply by virtue of IStart.List being an IReadOnlyList
start.List.Add(new C()); // no can do!
}
Whether this approach fits your application scenario well is for you to determine, but it's an approach that tries to avoid granular pattern matching on individual list items and aims at simplifying working with Start instances once they have been pattern-matched/cast to the correct Start<TBase> type.

Related

Trying to convert an C# anonymous type to a strong type

I'm trying to convert some anonymous type back to its original strong type class.
I have some legacy code (which I cannot touch) which create an anonymous class:
public class Cat : FooId
{
public int Id { get; set; }
public string Name { get; set; }
}
var result = new
{
Id = Mapper.Map<TFooId>(someCat)
};
NOTE: I've tried to make this fake class and interface similar to my code.
This then gives me:
result.GetType().ToString() : <>f__AnonymousType1``1[MyProject.Cat]
From here, I'm not sure how to convert this back to a MyProject.Cat instance?
I've tried (and fails):
(MyProject.Cat)result
(dynamic)result
but both fail. The dynamic doesn't throw an error ... but I can't access any properties in it.
C# is a statically typed language, and those two types are not in any way related to one another. Unless you're able to modify the code which defines those types, the way you'd convert from one to the other would be to create a new instance of the target type and populate it from the source object.
For example:
var resultCat = new Cat { Id = result.Id };
Edit: From comments it looks like it may be possible that the Id property on the result object may be an instance of Cat or some other object? You're going to need to do some debugging to find out what your types are.
But the overall concept doesn't really change. If you have an instance of Cat in your results then you can use that instance. If you don't then in order to create one you'd need to create a new instance and populate it with the data you have. Even if two types are intuitively or semantically similar, they are different types.
It's true what David said with regard to the fact that C# is a statically-typed language and that the new instance should be populated from the source the way he suggested.
However, there are work-arounds (though less performant) for that, such as reflection.
Consider you have a console app where you have defined ObjectExtensions as follows:
public static class ObjectExtensions
{
public static TOut Map<TOut>(this object #in)
where TOut : new()
{
TOut #out = new TOut();
if (#in?.GetType() is Type tin)
{
Type tout = typeof(TOut);
foreach ((PropertyInfo pout, PropertyInfo pin) in tout.GetProperties().Join(tin.GetProperties(), pi => pi.Name, pi => pi.Name, (pout, pin) => (pout, pin)))
{
pout.SetValue(#out, pin.GetValue(#in));
}
}
return #out;
}
}
And Class1 as follows:
public class Class1
{
public string A { get; set; } = "A";
public string B { get; set; } = "B";
public string C { get; set; } = "C";
public override string ToString()
{
return $"{{A={A}, B={B}, C={C}}}";
}
}
You will be able to map your anonymous type back to its original strongly-typed class like this:
Console.WriteLine(new { A = "Anonymous A", B = "Anonymous B", C = "Anonymous C" }.Map<Class1>());
Therefore the bloc above should show the following output:
{A=Anonymous A, B=Anonymous B, C=Anonymous C}
In this case, of course, I have assumed that Class1 (Cat in your example) must have a public parameterless constructor. That may not always be the case. There are more sophisticated scenarios of course that might involve other techniques for creating the object such as cloning or dependency injection. Just saying that the idea of yours is possible.

Why is it impossible to cast to a derived type [duplicate]

Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.
I have tried it and it creates a run-time error.
No. A reference to a derived class must actually refer to an instance of the derived class (or null). Otherwise how would you expect it to behave?
For example:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
If you want to be able to convert an instance of the base type to the derived type, I suggest you write a method to create an appropriate derived type instance. Or look at your inheritance tree again and try to redesign so that you don't need to do this in the first place.
No, that's not possible since assigning it to a derived class reference would be like saying "Base class is a fully capable substitute for derived class, it can do everything the derived class can do", which is not true since derived classes in general offer more functionality than their base class (at least, that's the idea behind inheritance).
You could write a constructor in the derived class taking a base class object as parameter, copying the values.
Something like this:
public class Base {
public int Data;
public void DoStuff() {
// Do stuff with data
}
}
public class Derived : Base {
public int OtherData;
public Derived(Base b) {
this.Data = b.Data;
OtherData = 0; // default value
}
public void DoOtherStuff() {
// Do some other stuff
}
}
In that case you would copy the base object and get a fully functional derived class object with default values for derived members. This way you can also avoid the problem pointed out by Jon Skeet:
Base b = new Base();//base class
Derived d = new Derived();//derived class
b.DoStuff(); // OK
d.DoStuff(); // Also OK
b.DoOtherStuff(); // Won't work!
d.DoOtherStuff(); // OK
d = new Derived(b); // Copy construct a Derived with values of b
d.DoOtherStuff(); // Now works!
Solution with JsonConvert (instead of typecast)
Today i faced the same issue and i found a simple and quick solution to the problem using JsonConvert.
var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);
I had this problem and solved it by adding a method that takes a type parameter and converts the current object into that type.
public TA As<TA>() where TA : Base
{
var type = typeof (TA);
var instance = Activator.CreateInstance(type);
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
property.SetValue(instance, property.GetValue(this, null), null);
}
return (TA)instance;
}
That means that you can use it in you code like this:
var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1
As many others have answered, No.
I use the following code on those unfortunate occasions when I need to use a base type as a derived type. Yes it is a violation of the Liskov Substitution Principle (LSP) and yes most of the time we favor composition over inheritance. Props to Markus Knappen Johansson whose original answer this is based upon.
This code in the base class:
public T As<T>()
{
var type = typeof(T);
var instance = Activator.CreateInstance(type);
if (type.BaseType != null)
{
var properties = type.BaseType.GetProperties();
foreach (var property in properties)
if (property.CanWrite)
property.SetValue(instance, property.GetValue(this, null), null);
}
return (T) instance;
}
Allows:
derivedObject = baseObect.As<derivedType>()
Since it uses reflection, it is "expensive". Use accordingly.
No it is not possible, hence your runtime error.
But you can assign an instance of a derived class to a variable of base class type.
As everyone here said, that's not possible directly.
The method I prefer and is rather clean, is to use an Object Mapper like AutoMapper.
It will do the task of copying properties from one instance to another (Not necessarily the same type) automatically.
In c# 9.0 you can try to use records for this. They have default copy constructor that copy all fields - no need to use reflection / constructor with all fields.
public record BaseR
{
public string Prop1 { get; set; }
}
public record DerivedR : BaseR
{
public DerivedR(BaseR baseR) : base(baseR) { }
public string Prop2 { get; set; }
}
var baseR = new BaseR { Prop1 = "base prob" };
var derivedR = new DerivedR(baseR) { Prop2 = "new prop" };
Not in the Traditional Sense... Convert to Json, then to your object, and boom, done! Jesse above had the answer posted first, but didn't use these extension methods which make the process so much easier. Create a couple of extension methods:
public static string ConvertToJson<T>(this T obj)
{
return JsonConvert.SerializeObject(obj);
}
public static T ConvertToObject<T>(this string json)
{
if (string.IsNullOrEmpty(json))
{
return Activator.CreateInstance<T>();
}
return JsonConvert.DeserializeObject<T>(json);
}
Put them in your toolbox forever, then you can always do this:
var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();
Ah, the power of JSON.
There are a couple of gotchas with this approach: We really are creating a new object, not casting, which may or may not matter. Private fields will not be transferred, constructors with parameters won't be called, etc. It is possible that some child json won't be assigned. Streams are not innately handled by JsonConvert. However, if our class doesn't rely on private fields and constructors, this is a very effective method of moving data from class to class without mapping and calling constructors, which is the main reason why we want to cast in the first place.
Expanding on #ybo's answer - it isn't possible because the instance you have of the base class isn't actually an instance of the derived class. It only knows about the members of the base class, and doesn't know anything about those of the derived class.
The reason that you can cast an instance of the derived class to an instance of the base class is because the derived class actually already is an instance of the base class, since it has those members already. The opposite cannot be said.
You can cast a variable that is typed as the base-class to the type of a derived class; however, by necessity this will do a runtime check, to see if the actual object involved is of the correct type.
Once created, the type of an object cannot be changed (not least, it might not be the same size). You can, however, convert an instance, creating a new instance of the second type - but you need to write the conversion code manually.
You have to use an object cloner/copier that will assign all the properties one by one.
Doing this by hand is inefficient and not future-proof. But serializing & deserializing to JSON and back is not the best solution, it is slow and very memory inefficient.
However, using AutoMapper is fast. PropMapper is even faster.
PS. Disclosure: I am a contributor at PropMapper open source project.
No, it is not possible.
Consider a scenario where an ACBus is a derived class of base class Bus. ACBus has features like TurnOnAC and TurnOffAC which operate on a field named ACState. TurnOnAC sets ACState to on and TurnOffAC sets ACState to off. If you try to use TurnOnAC and TurnOffAC features on Bus, it makes no sense.
class Program
{
static void Main(string[] args)
{
a a1 = new b();
a1.print();
}
}
class a
{
public a()
{
Console.WriteLine("base class object initiated");
}
public void print()
{
Console.WriteLine("base");
}
}
class b:a
{
public b()
{
Console.WriteLine("child class object");
}
public void print1()
{
Console.WriteLine("derived");
}
}
}
when we create a child class object,the base class object is auto initiated so base class reference variable can point to child class object.
but not vice versa because a child class reference variable can not point to base class object because no child class object is created.
and also notice that base class reference variable can only call base class member.
There actually IS a way to do this. Think about how you might use Newtonsoft JSON to deserialize an object from json. It will (or at least can) ignore missing elements and populate all the elements that it does know about.
So here's how I did it. A small code sample will follow my explanation.
Create an instance of your object from the base class and populate it accordingly.
Using the "jsonconvert" class of Newtonsoft json, serialize that object into a json string.
Now create your sub class object by deserializing with the json string created in step 2. This will create an instance of your sub class with all the properties of the base class.
This works like a charm! So.. when is this useful? Some people asked when this would make sense and suggested changing the OP's schema to accommodate the fact that you can't natively do this with class inheritance (in .Net).
In my case, I have a settings class that contains all the "base" settings for a service. Specific services have more options and those come from a different DB table, so those classes inherit the base class. They all have a different set of options. So when retrieving the data for a service, it's much easier to FIRST populate the values using an instance of the base object. One method to do this with a single DB query. Right after that, I create the sub class object using the method outlined above. I then make a second query and populate all the dynamic values on the sub class object.
The final output is a derived class with all the options set. Repeating this for additional new sub classes takes just a few lines of code. It's simple, and it uses a very tried and tested package (Newtonsoft) to make the magic work.
This example code is vb.Net, but you can easily convert to c#.
' First, create the base settings object.
Dim basePMSettngs As gtmaPayMethodSettings = gtmaPayments.getBasePayMethodSetting(payTypeId, account_id)
Dim basePMSettingsJson As String = JsonConvert.SerializeObject(basePMSettngs, Formatting.Indented)
' Create a pmSettings object of this specific type of payment and inherit from the base class object
Dim pmSettings As gtmaPayMethodAimACHSettings = JsonConvert.DeserializeObject(Of gtmaPayMethodAimACHSettings)(basePMSettingsJson)
You can use an Extention:
public static void CopyOnlyEqualProperties<T>(this T objDest, object objSource) where T : class
{
foreach (PropertyInfo propInfo in typeof(T).GetProperties())
if (objSource.GetType().GetProperties().Any(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()))
propInfo.SetValue(objDest, objSource.GetType().GetProperties().First(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()).GetValue(objSource));
}
In Code:
public class BaseClass
{
public string test{ get; set;}
}
public Derived : BaseClass
{
//Some properies
}
public void CopyProps()
{
BaseClass baseCl =new BaseClass();
baseCl.test="Hello";
Derived drv=new Derived();
drv.CopyOnlyEqualProperties(baseCl);
//Should return Hello to the console now in derived class.
Console.WriteLine(drv.test);
}
Might not be relevent, but I was able to run code on a derived object given its base. It's definitely more hacky than I'd like, but it works:
public static T Cast<T>(object obj)
{
return (T)obj;
}
...
//Invoke parent object's json function
MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(baseObj.GetType());
object castedObject = castMethod.Invoke(null, new object[] { baseObj });
MethodInfo jsonMethod = baseObj.GetType ().GetMethod ("ToJSON");
return (string)jsonMethod.Invoke (castedObject,null);
You can do this using generic.
public class BaseClass
{
public int A { get; set; }
public int B { get; set; }
private T ConvertTo<T>() where T : BaseClass, new()
{
return new T
{
A = A,
B = B
}
}
public DerivedClass1 ConvertToDerivedClass1()
{
return ConvertTo<DerivedClass1>();
}
public DerivedClass2 ConvertToDerivedClass2()
{
return ConvertTo<DerivedClass2>();
}
}
public class DerivedClass1 : BaseClass
{
public int C { get; set; }
}
public class DerivedClass2 : BaseClass
{
public int D { get; set; }
}
You get three benefits using this approach.
You are not duplicating the code
You are not using reflection (which is slow)
All of your conversions are in one place
I know this is old but I've used this successfully for quite a while.
private void PopulateDerivedFromBase<TB,TD>(TB baseclass,TD derivedclass)
{
//get our baseclass properties
var bprops = baseclass.GetType().GetProperties();
foreach (var bprop in bprops)
{
//get the corresponding property in the derived class
var dprop = derivedclass.GetType().GetProperty(bprop.Name);
//if the derived property exists and it's writable, set the value
if (dprop != null && dprop.CanWrite)
dprop.SetValue(derivedclass,bprop.GetValue(baseclass, null),null);
}
}
I combined some portions of the previous answers (thanks to those authors) and put together a simple static class with two methods that we're using.
Yes, it's simple, no it doesn't cover all scenarios, yes it could be expanded and made better, no it's not perfect, yes it could possibly be made more efficient, no it's not the greatest thing since sliced bread, yes there are full-on robust nuget package object mappers out there that are way better for heavy use, etc etc, yada yada - but it works for our basic needs though :)
And of course it will try to map values from any object to any object, derived or not (only the public properties that are named the same of course - ignores the rest).
USAGE:
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
// creates new object of type "RealPerson" and assigns any matching property
// values from the puppet object
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);
// OR
// create the person object on our own
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};
// maps and overwrites any matching property values from
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);
STATIC UTILITY CLASS:
public static class ObjectMapper
{
// the target object is created on the fly and the target type
// must have a parameterless constructor (either compiler-generated or explicit)
public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
{
// create an instance of the target class
Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));
// map the source properties to the target object
MapToExistingObject(sourceobject, targetobject);
return targetobject;
}
// the target object is created beforehand and passed in
public static void MapToExistingObject(object sourceobject, object targetobject)
{
// get the list of properties available in source class
var sourceproperties = sourceobject.GetType().GetProperties().ToList();
// loop through source object properties
sourceproperties.ForEach(sourceproperty => {
var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);
// check whether that property is present in target class and is writeable
if (targetProp != null && targetProp.CanWrite)
{
// if present get the value and map it
var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
}
});
}
}
You can use a copy constructor that immediately invokes the instance constructor, or if your instance constructor does more than assignments have the copy constructor assign the incoming values to the instance.
class Person
{
// Copy constructor
public Person(Person previousPerson)
{
Name = previousPerson.Name;
Age = previousPerson.Age;
}
// Copy constructor calls the instance constructor.
public Person(Person previousPerson)
: this(previousPerson.Name, previousPerson.Age)
{
}
// Instance constructor.
public Person(string name, int age)
{
Name = name;
Age = age;
}
public int Age { get; set; }
public string Name { get; set; }
}
Referenced the Microsoft C# Documentation under Constructor for this example having had this issue in the past.
With regarding #MarkusKnappenJohansson answer and below comments we can change his code extending extension function :) so it may update an existing deriving class instance via this code :
public static TDerived As<TDerived>(this Base baseInstance, TDerived updateDerivedInstance = null) where TDerived : Base, new()
{
Type baseType = typeof(Base);
Type derivedType = typeof(TDerived);
PropertyInfo[] properties = baseType.GetProperties();
object instanceDerived = null;
if (updateDerivedInstance == null)
{
instanceDerived = Activator.CreateInstance(derivedType);
}
else
{
instanceDerived = (object)(updateDerivedInstance);
}
foreach (PropertyInfo property in properties)
{
if (property.CanWrite)
{
property.SetValue(instanceDerived, property.GetValue(baseInstance, null), null);
}
}
return (TDerived)instanceDerived;
}
Usage for getting new derived Instance is var base = new Base(); base.Data = 1; var derived = base.As<Derived>(); Console.Write(derived.Data); // Would output 1
Usage for updating existing derived Instance is var derived = new Derived(); var base = new Base(); base.Data = 1; var derivedUpdated = base.As<Derived>(derived); Console.Write(derivedUpdated.Data); // Would output 1
Another solution is to add extension method like so:
public static void CopyProperties(this object destinationObject, object sourceObject, bool overwriteAll = true)
{
try
{
if (sourceObject != null)
{
PropertyInfo[] sourceProps = sourceObject.GetType().GetProperties();
List<string> sourcePropNames = sourceProps.Select(p => p.Name).ToList();
foreach (PropertyInfo pi in destinationObject.GetType().GetProperties())
{
if (sourcePropNames.Contains(pi.Name))
{
PropertyInfo sourceProp = sourceProps.First(srcProp => srcProp.Name == pi.Name);
if (sourceProp.PropertyType == pi.PropertyType)
if (overwriteAll || pi.GetValue(destinationObject, null) == null)
{
pi.SetValue(destinationObject, sourceProp.GetValue(sourceObject, null), null);
}
}
}
}
}
catch (ApplicationException ex)
{
throw;
}
}
then have a constructor in each derived class that accepts base class:
public class DerivedClass: BaseClass
{
public DerivedClass(BaseClass baseModel)
{
this.CopyProperties(baseModel);
}
}
It will also optionally overwrite destination properties if already set (not null) or not.
Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.
Not only explicit, but also implicit conversions are possible.
C# language doesn't permit such conversion operators, but you can still write them using pure C# and they work. Note that the class which defines the implicit conversion operator (Derived) and the class which uses the operator (Program) must be defined in separate assemblies (e.g. the Derived class is in a library.dll which is referenced by program.exe containing the Program class).
//In library.dll:
public class Base { }
public class Derived {
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
}
//In program.exe:
class Program {
static void Main(string[] args) {
Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
}
}
When you reference the library using the Project Reference in Visual Studio, VS shows squiggles when you use the implicit conversion, but it compiles just fine. If you just reference the library.dll, there are no squiggles.
How about:
public static T As<T>(this object obj)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));
}
Best way to add all base properties to derived item is use reflection in costructor. Try this code, without creating methods or instances.
public Derived(Base item) :base()
{
Type type = item.GetType();
System.Reflection.PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
try
{
property.SetValue(this, property.GetValue(item, null), null);
}
catch (Exception) { }
}
}
I disagree that it is not possible. You can do it like this:
public class Auto
{
public string Make {get; set;}
public string Model {get; set;}
}
public class Sedan : Auto
{
public int NumberOfDoors {get; set;}
}
public static T ConvertAuto<T>(Sedan sedan) where T : class
{
object auto = sedan;
return (T)loc;
}
Usage:
var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);
This is how I solved this for fields. You can do the same iteration through properties if you want. You may want to do some checks for null etc. but this is the idea.
public static DerivedClass ConvertFromBaseToDerived<BaseClass, DerivedClass>(BaseClass baseClass)
where BaseClass : class, new()
where DerivedClass : class, BaseClass, new()
{
DerivedClass derived = (DerivedClass)Activator.CreateInstance(typeof(DerivedClass));
derived.GetType().GetFields().ToList().ForEach(field =>
{
var base_ = baseClass.GetType().GetField(field.Name).GetValue(baseClass);
field.SetValue(derived, base_);
});
return derived;
}
You can just serialize the base object to JSON and then deserialize it to the derived object.
No, see this question which I asked - Upcasting in .NET using generics
The best way is to make a default constructor on the class, construct and then call an Initialise method

Which design pattern allows to get this architecture

I have the following objects :
Formula
Stock
Counter
etc ...
all these objects are called indicators and have common properties (Id, Name, Value...).
Each entity has its own properties:
Formula: FormulaExpression, FormulaCode, OperandsList ...
Stock: StockValue, StockLimit...
Counter: CounterIndex...
etc ...
So logically, i have to make indicator class containing the common properties, and for each entity i have to create a class that inherits from indicator.
Formula is a special indicator that can contain any type of indicators. The formula's indicators are named operands.
the operand object has the following properties:
operandId, operandCode, operandIndex
when i want to list the formula operands, i want to get objects which inherit from indicator, operand and entity type (create an object that have indicators properties, operand properties and stock properties for example)
which design pattern or which architecture allows me to have this behaviour?
To explain more the problem
The entities (Formula, stock, Counter..) are Indicators and not necessary Operands, Operands are Indicators too. Object Indicator is the primitive type of entities, we can create an Indicator and then decorate it to become a Formula for example and than decorate it to become an Operand when it is added to another Formula.
The best way to do it would be to use an expando object that is filled by each operand using polymorphic dispatch. The expando object lets you add custom properties, and the polymorphic dispatch lets you close your code against operands change.
You would start by using a base class for the Operand that contains your basic elements
public abstract class Operand
{
public int Id { get; set; }
public string Name { get; set; }
public dynamic BuildObject()
{
dynamic o = new ExpandoObject();
o.Id = Id;
o.Name = Name;
AddPropertiesToObject(o);
return o;
}
protected internal abstract void AddPropertiesToObject(dynamic o);
}
Then adding a new Operand type is very easy since you can control what you will add to it independently:
public class Stock : Operand
{
public double StockValue { get; set; }
protected internal override void AddPropertiesToObject(dynamic o)
{
// I decided to ignore the base class Id and Name
// adding them would be trivial, but may not be what you need since
// it would overwrite the base values...
// To add them you would have to wrap this virtual method call with
// a call to a function doing the insertion in the base class
o.StockValue = StockValue;
}
}
The Formula object would simply iterate on the contained operands and call their AddPropertiesToObject in turn (of course it can also add its own data but for the example I didn't include any)
public class Formula : Operand
{
public List<Operand> InnerOperands { get; set; }
protected internal override void AddPropertiesToObject(dynamic o)
{
foreach (var op in InnerOperands)
{
op.AddPropertiesToObject(o);
}
}
}
What I posted here may looks like a lot of code but it's actually very straightforward.
Most of the properties and constructors are there to simplify the script in the main function.
The base concept is to create a Generic Class for the operands that contains a reference to the base Indicator object it's created from.
Test this code in an empty project and it'll be very easy to understand from the output.
class Indicator{
// Common properties
}
class Counter : Indicator{
public int CounterIndex;
public Counter(int cI){
CounterIndex = cI;
}
public void Print()
{
Console.WriteLine("CounterIndex: {0}", CounterIndex);
}
}
class Operand{
// Common operand properties
}
class Operand<T> : Operand{
public T BaseIndicator;
public Operand(T bI){
BaseIndicator = bI;
}
}
class Formula : Indicator{
public string FormulaExpression;
public int FormulaCode;
public List<Operand> OperandsList = new List<Operand>();
public Formula(string fE, int fC){
FormulaExpression = fE;
FormulaCode = fC;
}
public void Print ()
{
Console.WriteLine ("FormulaExpression: {0}; FormulaCode: {1}",
FormulaExpression, FormulaCode);
if (OperandsList.Count == 0) {
return;
}
Console.WriteLine("Begin Operands: ");
foreach(Operand o in OperandsList){
if(o is Operand<Counter>){
Operand<Counter> cO = o as Operand<Counter>;
cO.BaseIndicator.Print();
}else if(o is Operand<Formula>){
Operand<Formula> fO = o as Operand<Formula>;
fO.BaseIndicator.Print();
}else{
// I'ts a simple Indicator
}
}
Console.WriteLine("End Operands");
}
}
class MainClass
{
public static void Main (string[] args)
{
Counter c1 = new Counter(2);
Counter c2 = new Counter(3);
Formula f1 = new Formula("a + b", 7);
Formula f2 = new Formula("a * b", 10);
Formula f = new Formula("a ^ b", 32);
f.OperandsList.Add(new Operand<Counter>(c1));
f.OperandsList.Add(new Operand<Formula>(f1));
f.OperandsList.Add(new Operand<Counter>(c2));
f.OperandsList.Add(new Operand<Formula>(f2));
f.Print();
Console.ReadLine();
}
}

C# inheritance. Derived class from Base class

I have a base class
public class A
{
public string s1;
public string s2;
}
I also have a derived class :
public class B : A
{
public string s3;
}
Suppose my program created an instance of class A.
A aClassInstance = new A();
some parameters were set:
aClassInstance.s1 = "string 1";
aClassInstance.s2 = "string 2";
At this point I would like to create an instance of class B. But I would like B to already have the values of my instance of class A.
This DID NOT Work:
public B bClassInstance = new B():
bClassInstance = (B)aClassInstance;
NEITHER DID THIS:
Made a clone method within Class A.
public B cloneA() {
A a = new A();
a = (A)this.MemberwiseClone()
return(B)a;
}
The VS code takes both of the above - but I get run-time errors
Please help
The base problem you have is, that you have to construct an instance of type B (which contains of cause the properties of type A). Your approach to clone an A instance won't work, because that gives you an instance of type A, which you can't convert to B.
I would write constructors for class A and B which takes a parameter of type A. The constructor of class B just passes the value to its base class A. The constructor of class A knows how to copy the fields to itself:
class A {
public A(A copyMe) {
s1 = copyMe.s1;
...
}
class B : A {
public B(A aInstance) : base(aInstance) {
}
}
Use it this way:
A a = new A();
a.s1 = "...";
B b = new B(a);
EDIT
When you don't want to have to change the constructor of A when adding new fields or props, you could use reflection to copy the properties. Either use a custom attribute to decorate what you want to copy, or copy just all props/fields of A:
public A (A copyMe) {
Type t = copyMe.GetType();
foreach (FieldInfo fieldInf in t.GetFields())
{
fieldInf.SetValue(this, fieldInf.GetValue(copyMe));
}
foreach (PropertyInfo propInf in t.GetProperties())
{
propInf.SetValue(this, propInf.GetValue(copyMe));
}
}
I havn't tried the code, but the point should become clear.
You could create a generic clone method in class A:
public T Clone<T>() where T : A, new() {
return new T() { a = this.a, b = this.b};
}
Or if you want to make the cloning extendable:
public T Clone<T>() where T : A, new() {
var result = new T();
this.CopyTo(result);
return result;
}
protected virtual void CopyTo(A other) {
other.a = this.a;
other.b = this.b;
}
You use it like this:
A a = new A();
// do stuff with a
// Create a B based on A:
B b = a.Clone<B>();
Please note: in your example, both the new A(), and the MemberwiseClone will create a new object of type A.
If you do not want to code the copy method yourself, you could look at a tool like AutoMapper.
After playing around and reading everything I could get my eyes on, both of the above solutions by GvS and Jan work.
However, the end result that I wanted to achieve is not to be forced to write out each member in the Copy methods.
Why:
a) If the class is edited and another object is added, the copy method will have to be updated. If someone else updates the class, they may forget to do this.
b) There may be a lot of members, and assigning them may be time consuming.
c) It just doesn't "feel" right. (Probably because I am very lazy).
Fortunately, I am not the only one with the same thoughts. Found a very very easy solution via the ValueInjector. (it has been discussed on these boards a lot).
After getting the dll (http://valueinjecter.codeplex.com/documentation)
The code becomes:
A a = new A();
a.s1 = "...";
B b = new B();
b.InjectFrom(a);
That's it :)
Obviously you would have to include:
using Omu.ValueInjecter;
And not forget to add it to the references.
You can also use a JSON serializer for example. You add a static method to your child-class which could then be called like this:
var porsche = Porsche.FromCar(basicCar);
Here, "Porsche" is the child class and "Car" is the base class. The function would then look something like this:
public class Porsche : Car
{
public static Porsche FromCar(Car basicCar)
{
// Create a JSON string that represents the base class and its current values.
var serializedCar = JsonConvert.SerializeObject(basicCar);
// Deserialize that base class string into the child class.
return JsonConvert.DeserializeObject<Porsche>(serializedCar);
}
// Other properties and functions of the class...
}
The trick here is, that properties that are available in the child but not the base, will be created with their default value, so null usually, depending on the type of the property. The deserialization also goes by the name of the property, so all properties are copied over.
I didn't test this code, but it should work, as I've done this once or twice before. Hope it helps someone.

C# inheritance casting one child to another

I have this simple structure: 1 parent, and two different childs.
public class Parent{}
public class ChildA : Parent{}
public class ChildB : Parent{}
I have an object objA of type ChildA, which I want to cast to ChildB. My naive approach says:
ChildA objA = new ChildA();
ChildB objB = (ChildB)objA;
But this is not directly possible - why? Is this because I need to implement some functions or because my naive approach is wrong?
Regards, Casper
It's not possible because the object objA refers to is not a ChildB. To put it another way, here's an example of what you're trying to do:
string x = "hi";
FileStream y = (FileStream) x;
They both have a common parent - System.Object - but they're completely different classes. What would you expect to happen if you tried to read from y?
Suppose your ChildB type has some field which is specific to that type - what would you expect that field's value to be after casting objA?
Why do you want to pretend that a ChildA is actually a ChildB? Could you maybe add a method in the parent class which does what you want? Add a method in ChildA like this:
ChildB ToChildB()
to perform an appropriate conversion?
It is not possible to simply cast one object other type even if thay have one parent, because thay maybe have different interfaces.
You need to implement explicit or implitic operator of ChildA (or ChildB).
class ClassA
{
public string Property1 { get; set; }
}
class ClassB
{
public string Property2 { get; set; }
public static implicit operator ClassB(ClassA classA)
{
return new ClassB() { Property2 = classA.Property1 };
}
}
or
class ClassA
{ {
public string Property1 { get; set; }
public static explicit operator ClassB(ClassA classA)
{
return new ClassB() { Property2 = classA.Property1 };
}
}
class ClassB
{
public string Property2 { get; set; }
}
And after implementing conversings operators following code will work fine:
var a = new ClassA() {Property1 = "test"};
ClassB b = (ClassB)a;
Console.WriteLine(b.Property2); // output is "test"
In first case you can omit explicitely type conversion and write just like this:
var a = new ClassA() {Property1 = "test"};
ClassB b = a;
And finally if you want to synchronize only properties of parent class you can write converter directly in parent:
class Parent
{
public string ParentProperty { get; set; }
public static T1 Convert<T1>(Parent obj) where T1 : Parent, new()
{
var result = new T1();
result.ParentProperty = obj.ParentProperty;
return result;
}
}
Using (ClassA and ClassB childs of Parent):
var a = new ClassA();
a.ParentProperty = "test";
ClassB b = Parent.Convert<ClassB>(a);
Console.WriteLine(b.ParentProperty); // output is "test"
You can't because ChildA is not a ChildB (you can only upcast from ChildA or ChildB to Parent, or downcast from Parent to ChildB or ChildA, there's no such thing as sidecasting in C#)
If you want to make the cast possible (a questionable endeavor, but well) you should implement an cast operator from ChildA to ChildB.
objA is NOT of type ChildB even if both are "children" from class Parent.
What you're trying to do won't work.
You can only case objA to it's base class (Parent) or to any common interface that ChildA and ChildB might implement.
Imagine, for a moment, that ChildB defined a method called Foo. How would your instance of objA deal with someone calling Foo? Clearly it couldn't work.
ChildA and ChildB are different types which share the same parent. Thus you can treat instances of both ChildA and ChildB as their base, Parent, but as they are different types you can't cast one to the other.
As others say ChildA is not ChildB. If ChildA and B have the same properties/functions then you should do:
public class Parent{}
public class Child : Parent{}
Child objA = new Child();
Child objB = objA;
But I gues this is only an example, you got a real live example why you want to achieve something like this?
I'm pretty sure I've come up with a way to simulate this, which might be useful at some point. Namely:
Inherit from Dictionary, or IDictionary and implement it if you need other base inheritance
Store properties in two locations - the dictionary and a real field
Keep a third boolean field that flags whether or not the real field has been set yet
If the real field has been set, take the real field
If it hasn't, take the dictionary value (as well as assigning it to the real field, and flagging)
If no dictionary value, act as though the property doesn't exist
Add a constructor that takes a Dictionary and populates this with the values from the Dictionary
You can now take a CatLikeObject inheriting from this base class, and by using the constructor (cast the cat to a Dictionary), generate an identical DogLikeObject (which will bark instead of meow, but still be called "Puss").
Disadvantages? Properties take up a LOT more space, and a lot of type safety gets shifted to runtime, let alone any performance loss that there may be (and there will definitely be some). Advantages? If you need to treat a Cat as a Dog temporarily, you can.
public class CSharepointStoredResults : Dictionary<string, object>
{
public CSharepointStoredResults(Dictionary<string, object> SourceDict = null)
{
// Populate class dictionary from passed dictionary. This allows for some degree of polymorphism sideways.
// For instance it becomes possible to treat one CSharepointStoredResults as another (roughly like treating
// a cat as a dog
foreach (string key in SourceDict.Keys) { this.Add(key, SourceDict[key]); }
}
public Type MyType
{
get {
if (!__MyType && !this.ContainsKey(bObj.GetPropertyNameFromExpression(() => this.MyType)))
{
// Neither a dictionary nor a field set
// return the field
}
else if (!__MyType)
{
// There is a dictionary entry, but no volatile field set yet.
__MyType = true;
_MyType = this[bObj.GetPropertyNameFromExpression(() => this.MyType)] as Type;
}
else
{
// Volatile value assigned, therefore the better source. Update the dictionary
this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = _MyType;
}
return _MyType;
}
set {
// Verify the value is valid...
if (!(value.IsInstanceOfType(typeof(CSharepointStoredResults))))
throw new ArgumentException("MyType can only take an instance of a CSharePointResults object");
_MyType = value;
this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = value;
}
}
private volatile Type _MyType;
private volatile bool __MyType;
}

Categories