ViewModel many to many relationship - c#

For our project, we would like to use ViewModels.
So we decided to create ViewModels for every object we can have :
So the ViewModel looks like this (GroupVM) :
public class GroupVM : EORTCViewModel<Prisma.BO.Group>
{
public GroupVM(Prisma.BO.Group group) : base(group) { }
public string Name
{
get
{
return this._Model.Name;
}
}
public string ShortName
{
get
{
return this._Model.ShortName;
}
}
public int Id
{
get
{
return this._Model.Id;
}
}
[ScriptIgnore]
public ICollection<StudyGroupVM> StudyGroups
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.StudyGroup>.ToViewModel<StudyGroupVM>(this._Model.StudyGroups);
}
}
}
The StudyVM :
public class StudyVM : EORTCViewModel<Prisma.BO.Study>
{
public StudyVM(Prisma.BO.Study study) : base(study) { }
public string Number
{
get
{
return this._Model.Number;
}
}
[ScriptIgnore]
public ICollection<StudyGroupVM> StudyGroups
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.StudyGroup>.ToViewModel<StudyGroupVM>(this._Model.StudyGroups);
}
}
}
and the intermediate object (StudyGroup) :
public class StudyGroupVM : EORTCViewModel<Prisma.BO.StudyGroup>
{
public StudyGroupVM(Prisma.BO.StudyGroup studyGroup) : base(studyGroup) { }
public StudyVM Study
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Study>.ToViewModel<StudyVM>(this._Model.Study);
}
}
public GroupVM Group
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Group>.ToViewModel<GroupVM>(this._Model.Group);
}
}
}
We would like to use a factory that would create ViewModels for every navigation properties.
So we wrote a generic ViewModel factory as follow :
public static class ViewModelFactory<T> where T : IEORTCObject
{
public static R ToViewModel<R>(T model) where R : EORTCViewModel<T>
{
return (R)Activator.CreateInstance(typeof(R), new object[] { model });
}
public static ICollection<R> ToViewModel<R>(ICollection<T> models) where R : EORTCViewModel<T>
{
ICollection<R> viewModels = new List<R>();
foreach (T model in models)
{
viewModels.Add((R)Activator.CreateInstance(typeof(R), new object[] { model }));
}
return viewModels;
}
}
The problem is that when we try to access the StudyGroups property from one of the end object of the relation, it creates correctly the object but then want to recreate the same object because it seems it tries to access the getter for the other end of the relation.
This cause a StackOverFlowException since it never stops (cycles).
Does any of you have any idea how I can solve this issue ?

Can you use memoization to cache your viemodel after it has been created once?
Something like:
public GroupVM Group
{
get
{
if(groupVM == null)
{
groupVM = Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Group>.ToViewModel<GroupVM>(this._Model.Group);
}
return groupVM;
}
}

Related

Inheriting 2 base classes in .NET not possible?

So I am reading that in .net it is not possible to inherit a second base class. How then Can you create an object that serves 2 functions from 2 classes? For example I have an object that I want to be a tool and a weapon. The first is public class SmithHammer : BaseTool the second would look like public class SmithHammer : BaseBashing The 2 classes BaseTool and BaseBashing can be used for the same item just not at the same time apparently. As a weapon I have it coded this way to call on the base class BaseBashing.
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithyHammer : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
public override int OldMinDamage { get { return 6; } }
public override int OldMaxDamage { get { return 18; } }
public override int OldSpeed { get { return 40; } }
public override int InitMinHits { get { return 31; } }
public override int InitMaxHits { get { return 60; } }
[Constructable]
public SmithyHammer()
: base(0x13E3)
{
Weight = 8.0;
Layer = Layer.OneHanded;
Name = "Smith Hammer";
}
public SmithyHammer(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
}
}
And in the second use I have it as a tool
namespace Server.Items
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithHammer : BaseTool
{
public override CraftSystem CraftSystem{ get{ return DefBlacksmithy.CraftSystem; } }
[Constructable]
public SmithHammer() : base( 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
[Constructable]
public SmithHammer( int uses ) : base( uses, 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
public SmithHammer( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Is it not possible to make this item do both functions?
There is a mechanism for such scenarios - interfaces. Classes in C# does not support multiple inheritance but support implementing multiple interfaces. In this case you can create two interfaces (or even more) representing required contracts (i.e. interfaces):
public interface IBashing
{
string Damage { get; }
int OldStrengthReq { get; }
// ...
// rest of properties/methods for bashing/weapon
}
public interface ITool
{
CraftSystem CraftSystem { get; }
// ...
}
And implement them both the Hammer class:
public class SmithHammer : IBashing, ITool
{
public string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public int OldStrengthReq { get { return 45; } }
public CraftSystem CraftSystem { get{ return DefBlacksmithy.CraftSystem; } }
// rest of implemetations
}
And clients can use this hammer class instance via interface or using type testing. For example if you introduce IItem interface to store everything in the inventory (i.e interface IBashing : IItem and interface ITool : IItem) it can look like this:
var inventory = new List<IItem>();
// add some items
// pick some i'th item:
var item = inventory[i];
var tool = item as ITool; // or use pattern matching here
if(tool != null)
{
// use tool
}
else
{
....
}
Sharing implementation is not that easy with interfaces (unless you can and want to use default interface implementations) but can be achieved via composition and wrapping, i.e.:
public class SmithyHammerBashing : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
}
public class SmithHammer : IBashing, ITool
{
private readonly SmithyHammerBashing Bashing = new SmithyHammerBashing(); // or construct some other way
public string Damage { get { return Bashing.Damage; } }
public int OldStrengthReq { get { return Bashing.OldStrengthReq; } }
// the same approach for ITool
}

Using single method to return possible different instance types

So I have got these 2 instance types "FirstType" and "SecondType" which inherit from the mother class "ContaBancaria". They both return text from different textboxes. Basically, they do the same thing, but I need 2 instances for 2 different list types (I probably don't think the list has anything to do with my question, so I'll proceed not to go in detail)
Here are the instances:
private FirstType AddTypeFirst()
{
return new FirstType(textBoxNumber.Text,
textBoxBalance.Text,
textBoxName.Text,
textBoxAddress.Text,
textBoxBirth.Text);
}
private SecondType AddTypeSecond()
{
return new SecondType(textBoxNumber.Text,
textBoxBalance.Text,
textBoxName.Text,
textBoxAddress.Text,
textBoxBirth.Text);
}
Is there a way to return these 2 instances with the same method type?
EDIT:
What I meant was to return these 2 different types of instances with 1 single method, for example:
private [type?] AddInstance()
{
return new [type*] textBoxNumber.Text, //* the type could be FirstType or SecondType
textBoxBalance.Text,
textBoxName.Text,
textBoxAddress.Text,
textBoxBirth.Text);
}
EDIT 2:
ContaBancaria looks like this:
abstract class ContaBancaria
{
public string number { get; set; }
public string balance { get; set; }
public Client data { get; set; }
}
And, since there's Client...
class Client
{
public string name;
public string address;
public string birth;
}
Hope you get me.
You can use generic method and derrived classes I think.
For example, you have two classes and you want to receive one of them. Those classes are named "FirstSon" and "SecondSon" and both of them are derrived from class "Father".
class Father
{
string myName;
public string MyName
{
get { return myName; }
set { myName = value; }
}
public Father()
{
myName = "John";
}
}
class FirstSon : Father
{
string mySecondName;
public string MySecondName
{
get { return mySecondName; }
set { mySecondName = value; }
}
public FirstSon()
{
mySecondName = "Bill";
}
}
class SecondSon : Father
{
int age;
public int Age
{
get { return age; }
set { age = value; }
}
string mySecondName;
public string MySecondName
{
get { return mySecondName; }
set { mySecondName = value; }
}
public SecondSon()
{
mySecondName = "Drake";
age = 21;
}
}
And you have method GetObject(). This method is generic. It receives type of class, then checks what type it has received and returnes the new object with the same type.
public static T GetObject<T>() where T: Father
{
var firstSon = new FirstSon();
var secondSon = new SecondSon();
if (firstSon.GetType() == typeof(T))
return (T)Convert.ChangeType(firstSon, typeof(T));
return (T)Convert.ChangeType(secondSon, typeof(T));
}
It uses method Convert.ChangeType(object value, Type conversonType) and allows you to convert your object to your type.
But I am not convinced that this is a good idea according to How do I make the return type of a method generic?
Assuming you want to return the proper type based on the list being added to, you will need to write your own generic Add function, and use Reflection to figure out the type:
public static class Ext {
public static void AddInstancia<T>(this List<T> aList) where T : class {
if (typeof(T) == typeof(FirstType))
aList.Add(AddTypeFirst() as T);
else
aList.Add(AddTypeSecond() as T);
}
}
I see no good reason to do this - after all, you know the type of the list, just call the correct function for that list...
Instead of using Reflection, you could also use dynamic if you add some functions to each sub-type:
public class FirstType : Parent {
public FirstType MakeChild() {
return new FirstType();
}
}
public class SecondType : Parent {
public SecondType MakeChild() {
return new SecondType();
}
}
public static class Static<T> where T : new() {
public static dynamic Value = new T();
}
public static class Ext {
public static void AddInstance<T>(this List<T> aList) where T : new() {
aList.Add(Static<T>.Value.MakeChild());
}
}
Which you can call like
var list1 = new List<FirstType>();
list1.AddInstance();

Making Validation Generic

I have the following C# code. Here the validations are kept outside the class to satisfy Open – Closed Principle. This is working fine. But the challenge is – the validations are not generic. It is specific to employee class (E.g DateOfBirthRuleForEmployee). How do I make the validations generic for all objects (DateOfBirthRuleForAnyObject).
Note: Make Generic <==> Make Type-Independent
Note: I have NameLengthRuleForEmployee validation also. New validation may come in future.
EDIT
Generic Method Example: Using “OfType” in LINQ
CODE
class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
employee.DateOfBirth = DateTime.Now;
employee.Name = "Lijo";
DateOfBirthRuleForEmployee dobRule = new
DateOfBirthRuleForEmployee();
NameLengthRuleForEmployee nameRule = new
NameLengthRuleForEmployee();
EmployeeManager employeeManager = new EmployeeManager();
employeeManager.AddRules(dobRule);
employeeManager.AddRules(nameRule);
bool result = employeeManager.validateEntity(employee);
Console.WriteLine(result);
Console.ReadLine();
}
}
public interface IEntity
{
}
public interface IRule<TEntity>
{
bool IsValid(TEntity entity);
}
public class DateOfBirthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee entity)
{
return (entity.DateOfBirth.Year <= 1975);
}
}
public class NameLengthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee employee)
{
return (employee.Name.Length < 5);
}
}
public class Employee : IEntity
{
private DateTime dateOfBirth;
private string name;
public DateTime DateOfBirth
{
get
{
return dateOfBirth;
}
set
{
dateOfBirth = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
public class EmployeeManager
{
RulesEngine<Employee> engine = new RulesEngine<Employee>();
public void AddRules(IRule<Employee> rule)
{
engine.AddRules(rule);
//engine.AddRules(new NameLengthRuleForEmployee());
}
public bool validateEntity(Employee employee)
{
List<IRule<Employee>> rulesList = engine.GetRulesList();
//No need for type checking. Overcame Invariance problem
bool status = true;
foreach (IRule<Employee> theRule in rulesList)
{
if (!theRule.IsValid(employee))
{
status = false;
break;
}
}
return status;
}
}
public class RulesEngine<TEntity> where TEntity : IEntity
{
private List<IRule<TEntity>> ruleList = new
List<IRule<TEntity>>();
public void AddRules(IRule<TEntity> rule)
{
//invariance is the key term
ruleList.Add(rule);
}
public List<IRule<TEntity>> GetRulesList()
{
return ruleList;
}
}
The challange is for your rules to know which property of what type to validate. You can either provide this by implementing an interface that provides just that as suggested by SLaks or by quessing it dynamically or by providing a concrete rule class with a bit more information on how to access the given property, e.g.:
class NameRule<T> : IRule<T>
{
private Func<T, string> _nameAccessor;
public NameRule(Func<T, string> nameAccessor)
{
_nameAccessor = nameAccessor;
}
public bool IsValid(T instance)
{
return _nameAccessor(instance).Length > 10;
}
}
this ofcourse can be used in the following way:
NameRule<Employee> employeeNameRule = new NameRule<Employee>(x => x.name);
employeeManager.addRule(employeeNameRule);

Save Observable Collection <T>

public class MyDoc
{
public string Private {set;get;}
public string Public {set;get;}
}
public class MyFind
{
public string Find {set;get;}
public string News {set;get;}
private ObservableCollection<MyDoc> _smalllist;
public ObservableCollection<MyDoc> SmallList
{
get
{
if (_smalllist == null)
{
_smalllist = new ObservableCollection<MyDoc>();
}
return _smalllist;
}
set
{
if (_smalllist != value)
{
_smalllist = value;
}
}
}
}
public class Ask
{
private ObservableCollection<MyFind> _Biglist;
public ObservableCollection<MyFind> BigList
{
get
{
if (_Biglist == null)
{
_Biglist = new ObservableCollection<MyFind>();
}
return _Biglist;
}
set
{
if (_Biglist != value)
{
__Biglist = value;
}
}
}
}
How can i save IsolatedStorage the Small list, and Big list ?
("Important : into the BigList need got 2 string and 1 ObservableCollection<> ").
We can see in class MyFind has got an ObservableCollection and 2 string in class MyAsk has got an ObservableCollection
You need to create your own serializable observable collection as this: Check this http://kentb.blogspot.com/2007/11/serializing-observablecollection.html
another option is to crate IList backing fields and create a wrapping ObservableCollection properties marked as Non-Serializable

Comparing 2 NHibernate loaded object problem

I have a class Client like that:
public class Client
{
public Person Pers { get; set; }
}
And I have 2 Person´s child class :
public class PersonType1 : Person {...}
public class PersonType2 : Person {...}
So, my Client could be PersonType1 or PersonType2...
I load 2 Client using NHibernate... And after that, I´m trying to compare than (the difference are on PersonType1 and PersonType2 attributes)...
I tried that:
public class ClientComparer : IComparer<Client>
{
public int Compare(Client __c1, Client __c2)
{
string _name1 = __c1.Person.GetType().Equals(typeof(PersonType2)) ? ((PersonType2)(__c1.Person)).Type2Att : ((PersonType1)(__c1.Person)).Type1Att ;
string _name2 = __c2.Person.GetType().Equals(typeof(PersonType2)) ? ((PersonType2)(__c2.Person)).Type2Att : ((PersonType1)(__c2.Person)).Type1Att;
if (_name1 == null)
{
if (_name2 == null)
{
return 0;
}
return -1;
}
if (_name2 == null)
{
return 1;
}
return _name1.CompareTo(_name2);
}
}
The problem is that __c1.Person.GetType() returs PersonProxy127b2a2f44f446089b336892a673643b instead of the correct type... It´s because of NHibernate...
How can I do that ? Ideas?
Thanks
Rather than having two different attributes on PersonType1 and PersonType2, define a single property in the base class Person and override it in each of the child classes. Using polymorphic behavior rather than explicit type-checking is better in any case, and essential when you're using NHibernate's proxied classes. Something like this might accomplish what you want:
public class Person
{
public string Name {get;}
}
public class PersonType2 : Person
{
private string something;
public override string Name
{
get
{
return something;
}
set
{
something = value;
}
}
}
public class PersonType2 : Person
{
private string somethingElse;
public override string Name
{
get
{
return somethingElse;
}
set
{
somethingElse = value;
}
}
}
public class Client
{
public int Compare(Client __c1, Client __c2)
{
return __c1.Pers.Name.CompareTo(__c2.Pers.Name);
}
}
Use the is operator instead of GetType():
public class ClientComparer : IComparer<Client>
{
public int Compare(Client __c1, Client __c2)
{
string _name1 = GetName(__c1.Person);
string _name2 = GetName(__c2.Person);
if (_name1 == null)
{
if (_name2 == null)
{
return 0;
}
return -1;
}
if (_name2 == null)
{
return 1;
}
return _name1.CompareTo(_name2);
}
private string GetName(Person person)
{
if (person is Person1)
{
return ((Person1)person).Type1Att;
}
else if (person is Person2)
{
return ((Person2)person).Type2Att;
}
else
{
throw new ArgumentException("Unhandled Person type.");
}
}
}

Categories

Resources