My classes are similar to these:
public class Root<TChild>
{
int ID {get;}
...
List<TChild> Children {get;}
}
public class Child
{
int IDChild {get;}
...
}
I need to add the reverse navigation property in Child class to access from Child its Root, but I don't know how to declare the property of Root<TChild> type.
Which type should be TChild in Child class?
I tried this in .net fiddle and seems to work just fine
public class Root<TChild>
{
int ID {get;}
List<TChild> Children { get; set; }
}
public class Child
{
int IDChild {get;}
Root<Child> MyRoot { get; set; }
}
// wherever
var root = new Root<Child> { Children = new List<Child>() };
root.Children.Add(new Child { MyRoot = root });
This works fine and problem is that you have two classes for same entry better is use one class for every entry in tree.
public class TreeEntity
{
private int id = 0;
private TreeEntity parent = null;
private IList<TreeEntity> childs = new List<TreeEntity>();
public TreeEntity(int id)
{
this.id = id;
}
public void AddChild(TreeEntity child)
{
childs.Add(child);
child.parent = this;
}
}
or maybe
public class TreeEntity<T>
{
private int id = 0;
private TreeEntity<T> parent = null;
private IList<TreeEntity<T>> childs = new List<TreeEntity<T>>();
private T data = null;
public TreeEntity(int id, T data)
{
this.id = id;
this.data = data;
}
public void AddChild(TreeEntity<T> child)
{
childs.Add(child);
child.parent = this;
}
}
however in your case
public class Root<TChild>
{
int ID {get;}
...
List<TChild> Children {get;}
...
public void addChild(T child)
{
Children.add(child)
child.setParent(this)
}
}
public class Child
{
int IDChild {get;}
Root<Child> parent;
...
public void setParent (Root<Child>)
{
this.parent = parent;
}
}
I have a list of source classes derived from a base source class and a list with destination classes derived from a base destination class. There is only one destination class corresponding to a source class. I want to make a generic converter which updates an existing destination object, given his corresponding source object.
Updated completely:
I have the following code:
using System;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
S1 newItem = new S1()
{
Age = 11,
Name = "John"
};
D1 oldItem = new D1()
{
Age = 10
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<S1, D1> convertor = new Convertor<S1, D1>(newItem, oldItem);
S2 newItem2 = new S2()
{
City = "London",
Name = "Lynda"
};
D2 oldItem2 = new D2()
{
City = "Paris"
};
Convertor<S2, D2> convertor2 = new Convertor<S2, D2>(newItem2, oldItem2);
Console.ReadKey();
}
}
public abstract class SourceDomain
{
public string Name { get; set; }
internal abstract void SetItem<Y>(Y oldItem) where Y : DestinationDomain;
}
public class S1 : SourceDomain
{
public int Age { get; set; }
internal override void SetItem<Y>(Y oldItem)
{
Console.WriteLine("here I want to update the age of oldItem (10) with the new value (11)");
//oldItem.Age = Age;
}
}
public class S2 : SourceDomain
{
public string City { get; set; }
internal override void SetItem<Y>(Y oldItem)
{
Console.WriteLine("here I want to update the city of oldItem Paris with the new value London");
// oldItem.City = City;
}
}
public class DestinationDomain { }
public class D1 : DestinationDomain
{
public int Age { get; set; }
}
public class D2 : DestinationDomain
{
public string City { get; set; }
}
public class Convertor<X, Y> where X : SourceDomain where Y : DestinationDomain
{
protected X item;
protected Y oldItem;
public Convertor(X newObject, Y oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of item type, the proper method, not the base one.
item.SetItem(oldItem);
}
}
}
SourceDomain and DestinationDomain are base classes and there are a lot of derived classes for each of them S1, S2, D1, D2, etc.
This converter receives two classes as types and two objects of that classes and tries to update the destination item of type Y with source item of type X.
In the above example, I want to change update the age of the D1 oldItem variable with 11, and the City oldItem2 with the "London" value, but I cannot access that properties in SetItem method.
This needs to be done with a combination of inheritance and generics, and we'll make the two work together with generic type constraints.
Here are the requirements as I understand them:
You've got some data you want to copy from Source to Destination; one kind of data has an Age, one has a City, maybe another has a Poodle or a SwimmingPool. We'll define an interface that says: "This is a data object which can copy its own properties from another object of the same type", and we'll put all our data in little classes which know how to copy themselves. The "I can copy things like me" interface doesn't know what properties will be copied; it just requires the concrete class to implement a method that knows those details internally. As far as this example goes it could be a base class, but my assumption is the “copyability” isn’t the core indentity of these objects. It’s not what they represent; it’s just one thing we need to be able to do with them along the way.
The other things we need are a "source thing", and a "destination thing". A source thing just needs to provide a data object that can be copied. A destination thing just needs to receive a data object that can be copied.
You confused yourself by trying to mix up the sources and destinations with the data items. If you're going crazy trying to make your class do two contradictory things at once, try breaking it up into two classes that each does one thing.
You never do anything with your SourceDomain Name property, so I won't either. If you need to, I'll leave that as an exercise.
public interface ICopyable<T>
{
void CopyFrom(T other);
}
internal class Program
{
private static void Main(string[] args)
{
var newItem = new SourceDomain<Person>
{
Item = new Person { Age = 11 },
Name = "John"
};
var oldItem = new DestinationDomain<Person>
{
Item = new Person { Age = 10 }
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<Person> convertor = new Convertor<Person>(newItem, oldItem);
var newItem2 = new SourceDomain<Location>()
{
Item = new Location { City = "London" },
Name = "Lynda"
};
var oldItem2 = new DestinationDomain<Location>()
{
Item = new Location { City = "Paris" }
};
Convertor<Location> convertor2 = new Convertor<Location>(newItem2, oldItem2);
Console.ReadKey();
}
}
public class SourceDomain<T>
{
public string Name { get; set; }
public T Item { get; set; }
}
public class DestinationDomain<T> where T : ICopyable<T>, new()
{
public string Name { get; set; }
public T Item { get; set; }
public void CopyItemFrom(T other)
{
if (Item == null)
{
Item = new T();
}
Item.CopyFrom(other);
}
}
// A person is a thing which can turn itself into a copy of another Person.
// You could define a class Wombat : ICopyable<Locomotive>, if you wanted to be
// able to convert Locomotives to Wombats. You'd just add another CopyFrom()
// overload, public void CopyFrom(Locomotive other).
public class Person : ICopyable<Person>
{
public int Age { get; set; }
public void CopyFrom(Person other)
{
Age = other.Age;
}
}
public class Location : ICopyable<Location>
{
public String City { get; set; }
public void CopyFrom(Location other)
{
City = other.City;
}
}
public class Convertor<X> where X : ICopyable<X>, new()
{
protected SourceDomain<X> item;
protected DestinationDomain<X> oldItem;
public Convertor(SourceDomain<X> newObject, DestinationDomain<X> oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of item type, the proper method, not the base one.
//newObject.Data = oldItem.Data;
oldItem.CopyItemFrom(item.Item);
}
}
Homework:
Modify this code so DestinationDomain.CopyItemFrom() receives the source itself, not the source's item.
I think it's better the way I wrote it. Think of reasons why I might have thought that.
Seriously, find out what ref does, and never again use a keyword in your code if you are only guessing about what it might mean. Don't just throw code at the wall, hoping it sticks. You'll get yourself in a lot of frustrating trouble that way.
Finally i have done this:
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
S1 newItem = new S1()
{
Age = 11,
Name = "John"
};
D1 oldItem = new D1()
{
Age = 10
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<S1, D1> convertor = new Convertor<S1, D1>(newItem, oldItem);
S2 newItem2 = new S2()
{
City = "London",
Name = "Lynda"
};
D2 oldItem2 = new D2()
{
City = "Paris"
};
Convertor<S2, D2> convertor2 = new Convertor<S2, D2>(newItem2, oldItem2);
Console.ReadKey();
}
}
public interface ICopyable<T>
{
void CopyFrom(T other);
}
public abstract class SourceDomain
{
public string Name { get; set; }
}
public class S1 : SourceDomain
{
public int Age { get; set; }
}
public class S2 : SourceDomain
{
public string City { get; set; }
}
public class DestinationDomain { }
public class D1 : DestinationDomain, ICopyable<S1>
{
public int Age { get; set; }
public void CopyFrom(S1 other)
{
Console.WriteLine("oldItem.Age " + Age + " new Age; = " + other.Age);
Age = other.Age;
Console.WriteLine("oldItem.Age " + Age + " new Age; = " + other.Age);
}
}
public class D2 : DestinationDomain, ICopyable<S2>
{
public string City { get; set; }
public void CopyFrom(S2 other)
{
City = other.City;
Console.WriteLine(" oldItem.City = City;");
}
}
public class Convertor<X, Y> where X : SourceDomain where Y : DestinationDomain, ICopyable<X>
{
protected X item;
protected Y oldItem;
public Convertor(X newObject, Y oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of X type, the proper method, not the base one.
oldItem.CopyFrom(item);
Console.WriteLine(item);
}
}
}
I'm using on a Xamarin Forms project Realm. I have a class A :
public class A: RealmObject
{
[PrimaryKey]
public string Id { get; set; }
public string Name { get; set; }
public A() : base()
{
Id= Guid.NewGuid().ToString();
Name = $"Unknown_{Id}";
}
}
And a class B which contains a list of A's objects :
public class B: RealmObject
{
[PrimaryKey]
public string Id{ get; set; }
public string Name { get; set; }
public IList<A> AList { get; }
public B() : base()
{
Id= Guid.NewGuid().ToString();
Name = $"Unknown_{Id}";
}
}
The IList Alist contains object which are already saved on Realm and i would like to save them like references.
The issue is that when i try to add on Realm a B object, i get the exception :
Realms.Exceptions.RealmObjectManagedByAnotherRealmException: Cannot start to manage an object with a realm when it's already managed by another realm
This exception appears on the line realm.Add(newB, update: true); in the code bellow
private void AddB(B b)
{
var realm = GetRealmInstance();
using (var trans = realm.BeginWrite())
{
var newB = new B();
newB.Name = b.Name;
newB.Id = b.Id;
foreach (var element in b.AList)
{
newB.Devices.Add(element);
}
realm.Add(newB, update: true);
trans.Commit();
});
OnChanged?.Invoke();
}
I have to precise that all objects in the AList are already saved on Realm.
Thanks in advance.
How about:
var newB = new B();
newB.Name = b.Name;
newB.Id = b.Id;
realm.Add(newB, update: true);
foreach (var element in b.AList)
{
newB.Devices.Add(element);
}
trans.Commit();
I can't figure out why MessageBox show "false" if nuovo.matrice refers to the same object but not maintain the array reassignment done by the method. Why nuovo.matrice == mat is false if they refers to the same object?
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
class Class1
{
public ClassType[] matrice;
public class ClassType
{
public string a { get; set; }
public int b { get; set; }
}
}
Class1.ClassType[] mat;
private void Form1_Load(object sender, EventArgs e)
{
Class1 test = new Class1();
Class1.ClassType prova = new Class1.ClassType();
test.matrice = new Class1.ClassType[1];
test.matrice[0] = prova;
mat = test.matrice;
mat[0].a = "rtuier";
mat[0].b = 94;
Modify nuovo = new Modify(mat);
nuovo.inizia();
MessageBox.Show((nuovo.matrice == mat).ToString());
}
class Modify
{
public Class1.ClassType[] matrice;
public Modify(Class1.ClassType[] mat)
{
matrice = mat;
}
public void inizia()
{
matrice[0].a = "asuidh";
matrice[0].b = 123;
Class1.ClassType[] newMatrice = new Class1.ClassType[2];
Class1.ClassType ins = new Class1.ClassType { a = "pollo", b = 456 };
newMatrice[0] = matrice[0];
newMatrice[1] = ins;
matrice = newMatrice;
}
}
}
}
The problem is, they don't ref the same object.. because you cannot alter the mat variable in the class. You get a copy of a reference and you're altering the copy. If you want to be able to modify a reference, you should wrap it in a class. Then you'll get a copy of the wrapper reference, but the Class1 field is unique.
Class wrap example:
public class ClassType
{
public string a { get; set; }
public int b { get; set; }
}
public class Class1
{
public ClassType[] classType;
}
public class Wrapper
{
public Class1 WrappedClass1;
}
public class Class2
{
public Wrapper Wrapped;
public Class2(Wrapper wrapper)
{
Wrapped = wrapper;
}
public void ChangeClass1()
{
WrappedClass1.WrappedClass1 = new Class1();
}
}
Class1 class1 = new Class1();
Wrapper wrapper = new Wrapper();
wrapper.WrappedClass1 = class1;
Class2 class2 = new Class2(wrapper);
class2.ChangeClass1();
MessageBox.Show(wrapper.WrappedClass1 == class2.Wrapped.WrappedClass1); // <--- true
I have following code:
public class A
{
public int MyProperty {get; set;}
}
public class B
{
A myInstance = new A();
myInstance.MyProperty = 10;
}
public class C
{
public void InvokeA()
{
//How to access MyPropery here?
BInstance = new B();
Console.WriteLine(B.myInstance.MyProperty.ToString());
}
}
I'm looking for a way to access MyProperty as written above. Inheritance is not an option since my class C is already inherited from some base class. A way without declaring any of the given classes as static would be nice!
Thanks,
Orz
Consider following classes:
public class A
{
public int MyProperty { get; set; }
}
public class B
{
public A GetAInstance()
{
A myInstance = new A();
myInstance.MyProperty = 10;
return myInstance;
}
}
public class C
{
private B BInstance;
public void InvokeA()
{
BInstance = new B();
Console.WriteLine(BInstance.GetAInstance());
}
}
and then you will create your C instance in Main:
static void Main(string[] args)
{
C cInstance = new C();
cInstance.InvokeA();
}
In order to accomplish your goal, you need to expose B.MyInstance as a property of the B class, just like you exposed A.MyProperty as a property of the A class.
Edit: Per the comments of others regarding use of the static keyword, here's what you might want your code to look like:
public class A
{
public int MyProperty { get; set; }
}
public static class B
{
static B()
{
MyInstance = new A();
MyInstance.MyProperty = 10;
}
public static A MyInstance { get; set; }
}
public class C
{
// not sure what your intention is here
public C()
{
System.Console.WriteLine(B.MyInstance.MyProperty.ToString()); // "10\n"
}
}
Yes. You can inherits classes from A to B something like this:
public class A
{
public int MyProperty {get; set;}
}
public class B : A
{
public B()
: A()
{
MyProperty = 1;
}
}
Now you can do:
(new B()).MyProperty
Or use Singleton approach to resolve:
public class B
{
private static _a;
public class A
{
public int MyProperty {get; set;}
}
public static A AA {
if (_a == null) {
_a = new A();
}
return _a;
}
}
This implmentation will return
B.A.MyProperty.ToString();