I have two Classes that derive from a mutual class A, which contains some properties (mainly stings and integers). Class B is a different class containing additional properties. More precisely,
public class A1 : A {
private B _bee;
public B Bee {
get { return _bee;}
set { _bee = value;}
}
}
public class A2 : A {
private List<B> _beeList;
public List<B> BeeList {
get { return _beeList;}
set { _beeList = value;}
}
}
Now, given an instance of A1, how can I make an instance of A2 containing the same information (i.e., the properties in the 'A' part, and the instance of 'B'). I tried the following - I wished it'd work, but knew it wouldn't... - (Let me call my instance of A1 resp. A2 by 'one' resp. 'two'):
A _a = (A)one; // This obv works
B _b = one.Bee;
A2 _a2 = (A2)_a; // Threw away the Bee - information, so should work imo
_a2.BeeList.Add(_b);
So how do I do this without populating all properties in A by hand?
using System.Reflection;
private void Convert(A1 _a1, A2 _a2)
{
foreach(PropertyInfo pi in typeof(A).GetProperties())
{
pi.SetValue(_a2,
pi.GetValue(_a1, null)
, null);
}
_a2.BeeList.Add(_a1.Bee);
}
this seemed to work for me
try using automapper.
automapper enables you to copy properties of a class to another class without writing much code.
ex:
Mapper.CreateMap<X, Y>();
Y y = Mapper.Map<X, Y>(x);
Automapper configuration would look like this:
Mapper.CreateMap<A1, A2>()
.ForMember(a2 => a2.BeeList, ctx => ctx.MapFrom(a1 => new List<B>{a1.Bee}));
A a1Object = new A1{Bee = new B()};
A2 a2Object = Mapper.Map<A2>(a1Object);
Related
I am wondering about the best approach to the below
I have a .NET Web application and I am changing the ORM provider I am using. To do this I have created a new solution and removed the previous ORM and implemented my new one. As there are lots of existing screens that work with the previous ORM I want to make sure that the same object is returned by both ORMS. As these are in two separate VS slns is there a simple way I can compare the complex objects that all the same properties have been loaded on to the object graph. I could set a breakpoint and compare them manually but I don't really want to do this?
If this is for testing purposes, you can use FluentAssertions to check this.
The following code declares two unrelated types, ClassA and ClassB which contain two nested classes both called A and B but of different types.
Therefore the containing classes and the nested classes are of unrelated types, but the names of the members are the same, and for the nested classes the types of the properties are the same.
You can use FluentAssertions to test if the two instances classA and classB are equivalent - even though they are of different types - as follows:
using System;
using FluentAssertions;
namespace Demo
{
class ClassA
{
public NestedClassA A;
public NestedClassB B;
}
class NestedClassA
{
public string S;
public int I;
}
class NestedClassB
{
public char C;
public double D;
}
class ClassB
{
public NestedClassC A;
public NestedClassD B;
}
class NestedClassC
{
public string S;
public int I;
}
class NestedClassD
{
public char C;
public double D;
}
internal class Program
{
private static void Main()
{
var nestedA = new NestedClassA {I = 1, S = "1"};
var nestedB = new NestedClassB {C = '1', D = 1};
var nestedC = new NestedClassC { I = 1, S = "1" };
var nestedD = new NestedClassD { C = '1', D = 1 };
var classA = new ClassA {A = nestedA, B = nestedB};
var classB = new ClassB {A = nestedC, B = nestedD};
classA.ShouldBeEquivalentTo(classB); // Passes
classB.ShouldBeEquivalentTo(classA); // Passes
classB.B.D = 2; // Now the two objects do not contain equivalent data.
classA.ShouldBeEquivalentTo(classB); // Fails.
}
}
}
So I am guessing it is not as simple as to implement the IEquatable interface and directly compare your instances using this. You have to be aware that implementing proper comparing methods will be the fastest way.
But there are slower, more flexible ways. I think what you want to do is:
Compare two objects of unknown types
Check if they contain class variables with the same name
Check if the class variables have matching types
Check if the values in the variables are the same
There is only one way to do that. And it is to throw System.Reflection at the problem. Mind that this solution will be considerably slower then all solutions that work with known types.
So you need your ComplexEquals function.
public static bool ComplexEquals(object obj1, object obj2)
{
if (obj1 == null && obj2 == null) return true;
if (obj1 == null || obj2 == null) return false;
var obj1Class = obj1.GetType();
var obj2Class = obj2.GetType();
/* Get the instance fields (all of them) of both classes. */
var obj1Fields = obj1Class.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
var obj2Fields = obj2Class.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
var checkedFields = new HashSet<String>();
foreach (var obj1Field in obj1Fields)
{
var fieldName = obj1Field.Name;
checkedFields.Add(fieldName);
var obj2Field = obj2Fields.Where(f => f.Name == fieldName).SingleOrDefault();
if (obj2Field == null) return false;
if (obj1Field.FieldType == obj2Field.FieldType && !(obj1Field.GetValue(obj1).Equals(obj2Field.GetValue(obj2)))) return false;
}
if (obj2Fields.Any(f => !checkedFields.Contains(f.Name))) return false;
return true;
}
This is a simple version that relies on the Equals function starting at the first level inside the unknown function. This may be sufficient or not. But I think that is a starting point that can be extended if required.
Assume that I have 2 classes: A & B
public class A
{
public string p1{get;set};
public string p2{get;set};
}
public class B : A
{
public string p3{get;set};
}
I have an object 'a' from class A, I want to create an object 'b' from class B which copy all property values from 'a'. Normally, I must do like following:
B b = new B();
b.p1 = a.p1;
b.p2 = a.p2;
With this solution, I must lose many codes if I must assign manually. Is there any solutions? Thanks.
You can look into using something like http://automapper.codeplex.com/ that will automatically map properties from a source object into a destination object for you using predefined rules.
then its as simple as configuring once like so:
Mapper.CreateMap<A, B>();
And creating your new object like this:
B b = Mapper.Map<B>(a);
You can write your own hydrator, if you like to, using reflection, so it will compare object properties, names and types.
Or you can use automapper as mentioned in another answer.
The third solution is to internalize adaption in code. Since "B" knows about "A", do
public class B : A
{
public string p3{get;set};
public void Hydrate{A a}
{
this.p1 = a.p1;
this.p2 = a.p2;
}
}
Then your code will be like this
B b = new B();
b.Hydrate(a);
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.
I'm trying to go the opposite way of what you would normally do.
I have two POCO classes A and B where B inherrits from A
public class A
{
public int Foo { get; set; }
}
public class B : A
{
public int Bar { get; set; }
}
B is ment as an extention to A with additional information.
I start by having an instance of class A
A a = new A { Foo = 1 };
And then I wish to extend the information in class A with the additional information and get the final class B. I could map every property from class A to the property in class B, but it does not make much sence to me:
A a = new A { Foo = 1 };
B b = new B { Foo = a.Foo, Bar = 2 };
Or in constructor
A a = new A { Foo = 1 };
B b = new B(a) { Bar = 2 }; // Mapping of value Foo is done in constructor of object B
The result is in eather case a manual mapping of values from object A to B.
There must be a smarter way to do this... any suggestions?
If you are actually changing type (rather than casting) - then if you have only a few classes, then just write conversion code - perhaps a ctor for B that accepts a template A. If you have a lot of classes... there are tricks you can do with either dynamic code or serialization. PropertyCopy in MiscUtil will do this, for example (using a dynamic Expression to do the work very quickly):
A a = new A { Foo = 1 };
B b = PropertyCopy<B>.CopyFrom(a);
b.Bar = 2;
I would regard the "smart" way as being your last suggestion - write a copy constructor for B that knows how to instantiate itself from an A.
I am working on a business problem in C#.NET. I have two classes, named C and W that will be instantiated independently at different times.
An object of class C needs to contain references to 0 ... n objects of class W, i.e. a C object can contain up to n W objects.
Each W object needs to contain a reference to exactly 1 object of class C, i.e. a W object is contained in one C object.
An object of class C is usually instantiated first. At a later point, its W contents are discovered, and instantiated. At this later point, I need to cross reference the C and W objects to each other.
What is a good design pattern for this? I actually have cases where I have three or four classes involved but we can talk about two classes to keep it simple.
I was thinking of something simple like:
class C
{
public List<W> contentsW;
}
class W
{
public C containerC;
}
This will work for the moment but I can foresee having to write a fair amount of code to keep track of all the references and their validity. I'd like to implement code down the road to do shallow refreshes of just the container and deep refreshes of all referenced classes. Are there any other approaches and what are their advantages?
Edit on 11/3:
Thanks to all for the good answers and good discussion. I finally chose jop's answer because that came closest to what I wanted to do, but the other answers also helped. Thanks again!
If you have the Martin Fowler's Refactoring book, just follow the "Change Unidirectional Association to Bidirectional" refactoring.
In case you don't have it, here's how your classes will look like after the refactoring:
class C
{
// Don't to expose this publicly so that
// no one can get behind your back and change
// anything
private List<W> contentsW;
public void Add(W theW)
{
theW.Container = this;
}
public void Remove(W theW)
{
theW.Container = null;
}
#region Only to be used by W
internal void RemoveW(W theW)
{
// do nothing if C does not contain W
if (!contentsW.Contains(theW))
return; // or throw an exception if you consider this illegal
contentsW.Remove(theW);
}
internal void AddW(W theW)
{
if (!contentW.Contains(theW))
contentsW.Add(theW);
}
#endregion
}
class W
{
private C containerC;
public Container Container
{
get { return containerC; }
set
{
if (containerC != null)
containerC.RemoveW(this);
containerC = value;
if (containerC != null)
containerC.AddW(this);
}
}
}
Take note that I've made the List<W> private. Expose the list of Ws via an enumerator instead of exposing the list directly.
e.g. public List GetWs() { return this.ContentW.ToList(); }
The code above handles transfer of ownership properly. Say you have two instances of C -- C1 and C2 - and the instances of W -- W1 and W2.
W1.Container = C1;
W2.Container = C2;
In the code above, C1 contains W1 and C2 contains W2. If you reassign W2 to C1
W2.Container = C1;
Then C2 will have zero items and C1 will have two items - W1 and W2. You can have a floating W
W2.Container = null;
In this case, W2 will be removed from C1's list and it will have no container. You can also use the Add and Remove methods from C to manipulate W's containers - so C1.Add(W2) will automatically remove W2 from it's original container and add it to the new one.
I generally do it something like this:
class C
{
private List<W> _contents = new List<W>();
public IEnumerable<W> Contents
{
get { return _contents; }
}
public void Add(W item)
{
item.C = this;
_contents.Add(item);
}
}
Thus, your Contents property is readonly and you add items through your aggregate's method only.
Hmmm, looks like you almost got it, with one minor glitch -- you gotta be able to control the addition to the list within C.
e.g.,
class C
{
private List<W> _contentsW;
public List<W> Contents
{
get { return _contentsw; }
}
public void AddToContents(W content);
{
content.Container = this;
_contentsW.Add(content);
}
}
For checking, you just have to iterate through your list, I think:
foreach (var w in _contentsW)
{
if (w.Container != this)
{
w.Container = this;
}
}
Not sure if that's what you need.
Do realize that there may be multiple instances of W that would have the same values but may have different C containers.
Expanding on Jons Answer....
You may need weak references if W isnt supposed to keep C alive.
Also...the add should be more complicated if you want to transfer ownership...
public void AddToContents(W content);
{
if(content.Container!=null) content.Container.RemoveFromContents(content);
content.Container = this;
_contentsW.Add(content);
}
One option for this would be to implement the IContainer and IComponent interfaces found under System.ComponentModel. C would be the container, and W the component. The ComponentCollection class would then serve as the storage for your W instances, and IComponent.Site would provide the back-link to C.
This is the pattern I use.
public class Parent {
public string Name { get; set; }
public IList<Child> Children { get { return ChildrenBidi; } set { ChildrenBidi.Set(value); } }
private BidiChildList<Child, Parent> ChildrenBidi { get {
return BidiChildList.Create(this, p => p._Children, c => c._Parent, (c, p) => c._Parent = p);
} }
internal IList<Child> _Children = new List<Child>();
}
public class Child {
public string Name { get; set; }
public Parent Parent { get { return ParentBidi.Get(); } set { ParentBidi.Set(value); } }
private BidiParent<Child, Parent> ParentBidi { get {
return BidiParent.Create(this, p => p._Children, () => _Parent, p => _Parent = p);
} }
internal Parent _Parent = null;
}
Obviously, I have classes BidiParent<C, P> and BidiChildList<C, P>, the latter of which implements IList<C>, etc. Behind-the-scenes updates are done through the internal fields, while updates from code which uses this domain model are done through the public properties.