I have the following setup:
public class Child<T>: BaseClass
{
public T Value;
}
public class IntChild: Child<int> { }
public class BoolChild: Child<bool> { }
public class FloatChild: Child<float> { }
public class MyProgram
{
public BaseClass Source;
public void SetValue(object val)
{
// I want to do something like the following
// ((Child) Source).Value = (val.GetType()) val;
// Instead, I have to do it like this
string temp = val.ToString();
switch (Source.GetType())
{
case "IntChild":
((IntChild) Source).Value = int.Parse(val.ToString());
break;
case "BoolChild":
((BoolChild) Source).Value = bool.Parse(val.ToString());
break;
case "FloatChild":
((FloatChild) Source).Value = float.Parse(val.ToString());
break;
}
}
}
I cannot modify the BaseClass (I could only overwrite ToString()).
How can I replace the switch with a simpler line of code? I want to do something like the following
((Child) Source).Value = (val.GetType()) val;
,instead of the switch. Is this even possible?
You should use the visitor pattern:
public abstract class BaseClassWithVisitor : BaseClass {
void AcceptVisitor(BaseClassVisitor visitor);
}
This means Child<T> become abstract too.
Make all Child<T> children class implements BaseClassWithVisitor.AcceptVisitor() method, so they are not abstract:
public class IntChild : Child<int> {
...
/// This method should be implemented in all Child<T> descendant classes
public override void AcceptVisitor(BaseClassVisitor visitor) { visitor.Visit(this); }
...
}
Then define the BaseClassVisitor interface :
public interface BaseClassVisitor {
void Visit(IntChild intChild);
void Visit(...); // all the other possible types
...
}
Then eventually create an implementation of the BaseClassVisitor that will do the operation you wanted:
public class SetValueVisitor : BaseClassVisitor {
void Visit(IntChild intChild) { intChild.Value = 1; }
void Visit(BoolChild boolChild) { boolChild.Value = false; }
...
}
Here is a complete example to make things clearer:
using System;
using System.Globalization;
namespace Visitor
{
class BaseClass
{
}
abstract class BaseClassWithVisitor : BaseClass
{
public abstract void AcceptVisitor(Visitor visitor);
}
abstract class Child<T> : BaseClassWithVisitor
{
public T Value;
}
class IntChild : Child<int>
{
public override void AcceptVisitor(Visitor visitor)
{
visitor.Visit(this);
}
}
class FloatChild : Child<float>
{
public override void AcceptVisitor(Visitor visitor)
{
visitor.Visit(this);
}
}
class StringChild : Child<string>
{
public override void AcceptVisitor(Visitor visitor)
{
visitor.Visit(this);
}
}
class Visitor
{
public object Value;
public void Visit(IntChild intChild)
{
intChild.Value = int.Parse(Value.ToString());
}
public void Visit(FloatChild floatChild)
{
floatChild.Value = float.Parse(Value.ToString(), CultureInfo.InvariantCulture);
}
public void Visit(StringChild stringChild)
{
stringChild.Value = Value.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var visitor = new Visitor { Value = "12345" };
var intChild = new IntChild();
intChild.AcceptVisitor(visitor);
visitor = new Visitor { Value = "1.2345" };
var floatChild = new FloatChild();
floatChild.AcceptVisitor(visitor);
visitor = new Visitor { Value = "Hello World" };
var stringChild = new StringChild();
stringChild.AcceptVisitor(visitor);
Console.WriteLine("intChild.Value = {0}", intChild.Value);
Console.WriteLine("floatChild.Value = {0}", floatChild.Value);
Console.WriteLine("stringChild.Value = {0}", stringChild.Value);
}
}
}
This will output:
intChild.Value = 12345
floatChild.Value = 1,2345
stringChild.Value = Hello World
You can do it via reflection without classes modifying at all:
public void SetValue(object val)
{
Source.GetType().GetProperty("Value").SetValue(Source, value);
}
Small variation of answer already provided by Slava Utesinov
// Only set value if implementation of Child<>.
// If any other derived class of BaseClass with value field, then dont set
if(source.GetType().BaseType != null
&& source.GetType().BaseType.IsGenericType
&& source.GetType().BaseType.GetGenericTypeDefinition() == typeof(Child<>))
{
Console.WriteLine("Is implementation of Child<>");
source.GetType().GetField("Value").SetValue(source, val);
}
else
{
Console.WriteLine("Not implementation of Child<>");
}
One option to consider:
public void SetValue(object val)
{
dynamic dynamicSource = Source;
dynamicSource.Value = val;
}
It is a similar approach to the reflection based approaches, but a little more concise.
Related
I am reshaping an entire system that does not use base classes and base interfaces.
My idea to do so is to extract all the common methods to a base classes and base interfaces.
So basically, we would have:
A base class SomeClassBase implementing an interface ISomeClassBase
A derived class SomeClassDerived implementing ISomeClassDerived (this interface deriving from ISomeClassBase)
Now the problem, how can I instantiate "_mySession" in the derived class (which has a different cast than in the base class), while preserving all the methods from the base class:
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession = MySession.Instance();
public SomeClassBase ()
{
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
public SomeClassDerived ()
{
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
One more thing, IMySessionDerived implements IMySessionBase.
Do not redefine _mySession Let it come from base class.
However in you Derived class you can still reassign.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public SomeClassDerived ()
{
_mySession = MySession.Instance(); //Declaration comes from base class automatically
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
If your IMySessionBase and IMySessionDerived are following Hierarchy, it should work. But in some rare cases, You might end up getting into a DoubleDispatchProblem.
As Pointed out in commens, If you want to do something from IMySessionDerived you can add a Property.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
IMySessionDerived _derivedSessionAccessor=> _mySession as IMySessionDerived;
}
Update: To fix the exact design problem here,
Instead of deriving from the base class, have it as a field. And inherit from interface. So Instead of doing above approach,
do like,
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession ;
public SomeClassBase ( IMySessionBase session)
{
_mySession=session;
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : , ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
private SomeClassBase _baseClassInstance;
public SomeClassDerived ()
{
_baseClassInstance=new SomeClassBase(_mySession);
//_mySession.connect();
}
public void doSomethingElse()
{
_baseClassInstance.doSomethingElse();
}
}
Pasting #Selvin answer instead of the link buried in the comments:
The trick here is to use the keyword "base()"
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
var o1 = new O1();
o1.DS1();
var o2 = new O2();
o2.DS1();
o2.DS2();
}
public class Session1
{
protected readonly Type ownerType;
public Session1(Type type)
{
ownerType = type;
}
public virtual void DS1([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class Session2 : Session1
{
public Session2(Type type):base(type) { }
public virtual void DS2([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class O1
{
private readonly Session1 t;
public O1() : this(new Session1(typeof(O1))) { }
protected O1(Session1 t)
{
this.t = t;
}
public void DS1()
{
t.DS1();
}
}
public class O2 : O1
{
private readonly Session2 t;
public O2() : this(new Session2(typeof(O2))) { }
protected O2(Session2 t) : base(t)
{
this.t = t;
}
public void DS2()
{
t.DS2();
}
}
}
I have a generic delegate like this:
public delegate T SomeHandler<T>(T input);
I have a generic class that take the delegate as a parameter to its constructor like this:
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Most of the time I would instantiate the class with a default handler unless some special case is needed. So I have some default handlers for the types I use:
public static class DefaultHandlers
{
public static string DefaultStringHandler(string input)
{
return input;
}
}
In some cases, the type is instantiated with a special handler that is specific to its implementation:
public class Example
{
private SomeClass<string> m_typicalCase;
private SomeClass<string> m_specialCase;
public Example()
{
m_typicalCase = new SomeClass<string>(DefaultHandlers.DefaultStringHandler);
m_specialCase = new SomeClass<string>(SpecialHandler);
}
private string SpecialHandler(string input)
{
string result;
// Do something special
return result;
}
}
I want to create a default constructor for SomeClass that always instantiates the class with the same default handler for that type, but since the type is not know at compile time, I can't return the delegate that is the right type.
public class SomeClass<T>
{
...
public SomeClass()
{
m_handler = DefaultHandlers.GetDefaultHandler<T>();
}
...
}
Like this
public static class DefaultHandlers
{
public static SomeHandler<T> GetDefaultHandler<T>()
{
if (typeof(T) == typeof(string))
{
return DefaultStringHandler;
}
}
}
This does not work becuase DefaultStringHandler returns a string and the method expects T.
The only way that I have found to do this is the make a type-specific subclass of SomeClass that overloads the default constructor:
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
: base(DefaultHandlers.DefaultStringHandler)
{
}
public SomeStringClass(SomeHandler<string> handler)
: base(handler)
{
}
}
It would be fun if generic types could have type-specific overloaded constructors that are used when instantiating the class of a specific type:
public class Foo<T>
{
public Foo<string>(string input)
{
}
public Foo<int>(int input)
{
}
public Foo(T input)
{
}
}
There must be a more elegant way to do with with a design pattern, Strategy maybe?
You could utilize dynamic to get something like SomeClass<string>():
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class SomeClass<T>
{
private static readonly Func<T,T> FALL_BACK_HANDLER = a => a; //or what have you
private readonly Func<T,T> m_handler;
public SomeClass(Func<T,T> handler)
{
m_handler = handler;
}
public SomeClass()
{
m_handler = DefaultHandler.For<T>() ?? FALL_BACK_HANDLER;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
Console.WriteLine(result);
}
}
public static class DefaultHandler
{
public static Func<T,T> For<T>()
{
return TypeAware<T>.Default;
}
private static class TypeAware<T>
{
private static readonly Func<T,T> DEFAULT;
static TypeAware()
{
var type = typeof(T);
if (type == typeof(string))
{
DEFAULT = a => DefaultHandler.StringHandler((dynamic) a);
}
else if (type == typeof(int))
{
DEFAULT = a => DefaultHandler.IntHandler((dynamic) a);
}
else
{
DEFAULT = null;
}
}
public static Func<T,T> Default { get { return DEFAULT; } }
}
public static string StringHandler(string a)
{
return a + " The default handler does some stuff!";
}
public static int IntHandler(int a)
{
return a + 2;
}
}
}
You would then consume SomeClass as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class Program
{
public static void Main(string[] args)
{
var someStringObj = new SomeClass<string>();
someStringObj.DoSomeStuff("Hello World.");//prints "Hello World. The default handler does some stuff!"
var someIntObj = new SomeClass<int>();
someIntObj.DoSomeStuff(1);//prints 3
var someCustomDoubleObj = new SomeClass<double>(d => d - 2);
someCustomDoubleObj.DoSomeStuff(3);//prints 1
Console.Read();
}
}
}
Building on Jon Skeet and Alexei Levenkovs comments. From what I understand, something like this might be what you're after?
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass()
{
m_handler = (T input) => input;
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Another way would be to move the string-specific behaviour into a separate class and simply make an instance of that class if you want specific behaviour tied to a specific type
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
protected SomeHandler<T> m_handler;
protected SomeClass()
{
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
{
m_handler = DefaultStringHandler;
}
private string DefaultStringHandler(string input)
{
// Do default string stuff here...
return input;
}
public SomeStringClass(SomeHandler<string> handler):base(handler)
{
}
}
I have an interface
using ClassAbstractFactory;
public interface IPlugin
{
AbstractFactory GetFactory();
}
and an AbstractFactory
public abstract class AbstractFactory
{
public abstract AbstractCake CreateCake();
public abstract AbstractBox CreateBox();
}
public abstract class AbstractCake
{
public abstract void Interact(AbstractBox box);
}
public abstract class AbstractBox
{
}
and I have .dll that inherit AbstractCake
public class ChocolateCake : AbstractCake
{
private bool _isPacked;
private bool _isDecorated;
private string _nameOfCake;
public ChocolateCake()
{
_isPacked = false;
_isDecorated = false;
_nameOfCake = "Шоколадный";
}
public bool IsPacked
{
get { return _isPacked; }
}
public bool IsDecorated
{
get { return _isDecorated; }
}
public string NameOfCake { get; set; }
public override void Interact(AbstractBox box)
{
_isPacked = true;
}
}
I load dll like this:
public IPlugin LoadAssembly(string assemblyPath)
{
Assembly ptrAssembly = Assembly.LoadFile(assemblyPath);
foreach (Type item in ptrAssembly.GetTypes())
{
if (!item.IsClass) continue;
if (item.GetInterfaces().Contains(typeof(IPlugin)))
{
return (IPlugin)Activator.CreateInstance(item);
}
}
throw new Exception("Invalid DLL, Interface not found!");
}
List<IPlugin> list = new List<IPlugin>();
foreach (var assemblyPath in GetPathsListToDll())
{
list.Add(LoadAssembly(assemblyPath));
}
How can I acess to attributes in my ChocolateCake,to use them like
foreach (var str in list)
{
Boolean a = str.GetFactory().GetCake().CreateCake().IsPacked;
}
or like this
string a = str.GetFactory().GetCake().CreateCake().NameOfCake;
or like this
str.GetFactory().GetCake().CreateCake().NameOfCake("Something");
or like this
str.GetFactory().GetCake().CreateCake().IsDecorated(true);
The problem here is that the AbstractFactory has a method that returns AbstractCake, and AbstractCake itself has no properties at all. As it stands, you would need to downcast the Cake (direct, or with the as keyword) to a ChocolateCake prior to accessing any of its properties, which is really messy:
string a = (ChocolateCake)(str.GetFactory().CreateCake()).NameOfCake;
Here are some considerations:
Move the properties which are common to all types of cake into AbstractCake, e.g. NameOfCake, IsPacked and IsDecorated
Given that the AbstractFactory and AbstractCake classes do not have any implementation at all, consider changing these to interfaces instead of abstract classes, i.e. ICakeFactory and ICake. Concrete implementations will be ChocolateCakeFactory and ChocolateCake as before.
Consumers of the factory and the cake should now only access what is exposed on the interfaces (ICakeFactory, ICake and IBox), and not need to do any down casting or make any assumptions about the actual concrete type of Cake etc.
i.e.
public interface ICake
{
void Interact(IBox box);
bool IsPacked { get; }
bool IsDecorated { get; }
string NameOfCake { get; set; }
}
public class ChocolateCake : ICake
{
private bool _isPacked;
private bool _isDecorated;
private string _nameOfCake;
public ChocolateCake() // ctor is not on the interface and is implementation detail
{
_isPacked = false;
_isDecorated = false;
_nameOfCake = "Шоколадный";
}
public void Interact(IBox box) {...}
public bool IsPacked { get { return _isPacked; } }
public bool IsDecorated { get { return _isDecorated; } }
// ...
}
public interface ICakeFactory
{
ICake CreateCake();
IBox CreateBox();
}
public class ChocolateCakeFactory : ICakeFactory
{
public ICake CreateCake() {return new ChocolateCake();}
public IBox CreateBox() {return new ChocolateCakeBox();}
}
Re : Usage
It is highly unlikely that you would ever do this:
string a = str.GetFactory().GetCake().CreateCake().NameOfCake;
str.GetFactory().GetCake().CreateCake().NameOfCake = "Something"; // Prop setter
as this would create a new cake instance each time (and discard the instance). How about:
class Bakery
{
private readonly ICakeFactory _cakeFactory;
public Bakery(ICakeFactory cakeFactory)
{
Contract.Requires(cakeFactory != null);
cakeFactory = _cakeFactory;
}
bool BakeStuff()
{
var cake = _cakeFactory.CreateCake();
cake.NameOfCake = "StackOverflow";
return cake.IsDecorated && cake.IsPacked;
}
}
Edit, Re Raise change Events
This involves implementing INotifyPropertyChanged
public interface ICake : INotifyPropertyChanged
Which you can then raise on your mutable properties, e.g.
public string NameOfCake
{
get { return _nameOfCake} ;
set {
var propChanged = PropertyChanged;
if (propChanged != null && value != _nameOfCake)
{
propChanged(this, new PropertyChangedEventArgs("NameOfCake"));
}
_nameOfCake = value;
}
}
And subscribe like so
var cake = new ChocolateCake();
cake.PropertyChanged += (sender, eventArgs)
=> Console.WriteLine("Property {0} has changed", eventArgs.PropertyName);
Would this work?
public abstract class AbstractFactory
{
public abstract TCake CreateCake<TCake>() where TCake : AbstractCake, new();
public abstract AbstractBox CreateBox();
}
...
var cake = str.GetFactory().CreateCake<ChocolateCake>();
I have an abstract base class Base which has some common properties, and many derived ones which implement different logic but rarely have additional fields.
public abstract Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
}
Sometimes I need to clone the derived class. So my guess was, just make a virtual Clone method in my base class and only override it in derived classes that have additional fields, but of course my Base class wouldn't be abstract anymore (which isn't a problem since it only has a protected constructor).
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone() { return new Base(); }
}
public A : Base { }
public B : Base { }
The thing is, since I can't know the type of the derived class in my Base one, wouldn't this lead to have a Base class instance even if I call it on the derived ones ? (a.Clone();) (actually after a test this is what is happening but perhaps my test wasn't well designed that's why I have a doubt about it)
Is there a good way (pattern) to implement a base Clone method that would work as I expect it or do I have to write the same code in every derived class (I'd really like to avoid that...)
Thanks for your help
You can add a copy constructor to your base class:
public abstract Base
{
protected int field1;
protected int field2;
protected Base() { ... }
protected Base(Base copyThis) : this()
{
this.field1 = copyThis.field1;
this.field2 = copyThis.field2;
}
public abstract Base Clone();
}
public Child1 : Base
{
protected int field3;
public Child1 () : base() { ... }
protected Child1 (Child1 copyThis) : base(copyThis)
{
this.field3 = copyThis.field3;
}
public override Base Clone() { return new Child1(this); }
}
public Child2 : Base
{
public Child2 () : base() { ... }
protected Child (Child copyThis) : base(copyThis)
{ }
public override Base Clone() { return new Child2(this); }
}
public Child3 : Base
{
protected int field4;
public Child3 () : base() { ... }
protected Child3 (Child3 copyThis) : base(copyThis)
{
this.field4 = copyThis.field4;
}
public override Base Clone()
{
var result = new Child1(this);
result.field1 = result.field2 - result.field1;
}
}
Just override the Clone and have another method to CreateInstance then do your stuff.
This way you could have only Base class avoiding generics.
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone()
{
var bc = CreateInstanceForClone();
bc.field1 = 1;
bc.field2 = 2;
return bc;
}
protected virtual Base CreateInstanceForClone()
{
return new Base();
}
}
public A : Base
{
protected int fieldInA;
public override Base Clone()
{
var a = (A)base.Clone();
a.fieldInA =5;
return a;
}
protected override Base CreateInstanceForClone()
{
return new A();
}
}
I did something similar as Alexander Simonov, but perhaps simpler. The idea is (as I said in a comment) to have just one Clone() in the base class and leave all the work to a virtual CloneImpl() which each class defines as needed, relying on the CloneImpl()s of the base classes.
Creation of the proper type is left to C#'s MemberwiseClone() which will do whatever it takes for the object that's calling. This also obviates the need for a default constructor in any of the classes (none is ever called).
using System;
namespace CloneImplDemo
{
// dummy data class
class DeepDataT : ICloneable
{
public int i;
public object Clone() { return MemberwiseClone(); }
}
class Base: ICloneable
{
protected virtual Base CloneImpl()
{
// Neat: Creates the type of whatever object is calling.
// Also obviates the need for default constructors
// (Neither Derived1T nor Derived2T have one.)
return (Base)MemberwiseClone();
}
public object Clone()
{
// Calls whatever CloneImpl the
// actual calling type implements.
return CloneImpl();
}
}
// Note: No Clone() re-implementation
class Derived1T : Base
{
public Derived1T(int i) { der1Data.i = i; }
public DeepDataT der1Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived1T cloned = (Derived1T)base.CloneImpl();
cloned.der1Data = (DeepDataT)der1Data.Clone();
return cloned;
}
}
// Note: No Clone() re-implementation.
class Derived2T : Derived1T
{
public Derived2T(int i1, int i2) : base(i1)
{
der2Data.i = i2;
}
public string txt = string.Empty; // copied by MemberwiseClone()
public DeepDataT der2Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived2T cloned = (Derived2T)base.CloneImpl();
// base members have been taken care of in the base impl.
// we only add our own stuff.
cloned.der2Data = (DeepDataT)der2Data.Clone();
return cloned;
}
}
class Program
{
static void Main(string[] args)
{
var obj1 = new Derived2T(1,2);
obj1.txt = "this is obj1";
var obj2 = (Derived2T)obj1.Clone();
obj2.der1Data.i++;
obj2.der2Data.i++; // changes value.
obj2.txt = "this is a deep copy"; // replaces reference.
// the values for i should differ because
// we performed a deep copy of the DeepDataT members.
Console.WriteLine("obj1 txt, i1, i2: " + obj1.txt + ", " + obj1.der1Data.i + ", " + obj1.der2Data.i);
Console.WriteLine("obj2 txt, i1, i2: " + obj2.txt + ", " + obj2.der1Data.i + ", " + obj2.der2Data.i);
}
}
}
Output:
obj1 txt, i1, i2: this is obj1, 1, 2
obj2 txt, i1, i2: this is a deep copy, 2, 3
You could do something like this:
public class Base<T> where T: Base<T>, new()
{
public virtual T Clone()
{
T copy = new T();
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base<A>
{
public override A Clone()
{
A copy = base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
private void Test()
{
A a = new A();
A aCopy = a.Clone();
}
But i doubt that it will bring something useful. I'll create another example..
I got another idea using the Activator class:
public class Base
{
public virtual object Clone()
{
Base copy = (Base)Activator.CreateInstance(this.GetType());
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base
{
public override object Clone()
{
A copy = (A)base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
A a = new A();
A aCopy = (A)a.Clone();
But i would go for the Alexander Simonov answer.
If performance is not important for your case, you can simplify your code by creating just one general clone method which can clone whatever to whatever if properties are same:
Base base = new Base(){...};
Derived derived = XmlClone.CloneToDerived<Base, Derived>(base);
public static class XmlClone
{
public static D CloneToDerived<T, D>(T pattern)
where T : class
{
using (var ms = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(ms))
{
Type typePattern = typeof(T);
Type typeTarget = typeof(D);
XmlSerializer xmlSerializerIn = new XmlSerializer(typePattern);
xmlSerializerIn.Serialize(writer, pattern);
ms.Position = 0;
XmlSerializer xmlSerializerOut = new XmlSerializer(typeTarget, new XmlRootAttribute(typePattern.Name));
D copy = (D)xmlSerializerOut.Deserialize(ms);
return copy;
}
}
}
}
Found this question while trying to solve this exact problem, had some fun with LINQPad while at it.
Proof of concept:
void Main()
{
Person p = new Person() { Name = "Person Name", Dates = new List<System.DateTime>() { DateTime.Now } };
new Manager()
{
Subordinates = 5
}.Apply(p).Dump();
}
public static class Ext
{
public static TResult Apply<TResult, TSource>(this TResult result, TSource source) where TResult: TSource
{
var props = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in props)
{
p.SetValue(result, p.GetValue(source));
}
return result;
}
}
class Person
{
public string Name { get; set; }
public List<DateTime> Dates { get; set; }
}
class Manager : Person
{
public int Subordinates { get; set; }
}
I have an <asp:Label> I wish to populate depending on the Generic object that I pass to it.
At the moment I have the following code:-
private void PopulateEnglishQuestion(int questionId)
{
ReportQuestion reportQuestion = questionsBll.GetReportQuestions().Where(x=> x.ReportQuestionId == questionId).FirstOrDefault();
PopulateLabels(reportQuestion);
}
private void PopulateTranslatedQuesiton(int questionId)
{
ReportQuestionTranslation reportQuestionTranslation = questionsBll.GetReportQuestionsTranslation().Where(x => x.QuestionId == questionId).FirstOrDefault();
PopulateLabels(reportQuestionTranslation);
}
private void PopulateLabels<T>(T item)
{
lblQuestionTitle.Text = typeof (T) == typeof (ReportQuestion)
? ((ReportQuestion) (item)).ReportQuestionTitle
: ((ReportQuestionTranslation) (item)).ReportQuestionTitleTrans;
}
How can I get the method PopulateLabels to work properly?
You should use an interface both ReportQuestion and ReportQuestionTranslation implement:
interface IQuestion
{
string TitleText;
}
Then, use the following code:
public void PopulateLabels(IQuestion item)
{
lblQuestionTitle.Text = item.TitleText;
}
Use an interface.
public interface IQuestion
{
string Title { get; }
}
public class ReportQuestion : IQuestion
{
public string Title { get { return ReportQuestionTitle; } }
}
public class ReportQuestionTranslation: IQuestion
{
public string Title { get { return ReportQuestionTitleTrans; } }
}
private void PopulateLabels(IQuestion item)
{
lblQuestionTitle.Text = item.Title;
}
Or use method overloading:
public void PopulateTitle(ReportQuestion question)
{
lblQuestionTitle.Text = question.ReportQuestionTitle;
}
public void PopulateTitle(ReportQuestionTranslation question)
{
lblQuestionTitle.Text = question.ReportQuestionTitleTrans;
}
Unrecommended:
public class QuestionTitleFormatter
{
public string GetTitle(object question)
{
if(question is ReportQuestion)
return ((ReportQuestion)question).ReportQuestionTitle;
if(question is ReportQuestionTranslation)
return ((ReportQuestionTranslation)question).ReportQuestionTitleTrans;
throw new NotImplementedException(string.Format("{0} is not supported", questionType.Name);
}
}
public void PopulateTitle(object question)
{
var formatter = new QuestionTitleFormatter();
lblQuestionTitle.Text = formatter.GetTitle(question);
}
The ToString() approach would be something like this:
class ReportQuestion {
public override string ToString() { return ReportQuestionTitle; }
...
}
class ReportQuestionTranslation{
public override string ToString() { return ReportQuestionTitleTrans; }
...
}
assuming that I answered my own question correctly in the comment above asking where the string will come from.
You could just override ToString() on those objects and not worry about any transformations or types in PopulateLabel.