Force EF 5 or 6 to map interface member - c#

The question is very simple and direct: What do I have to do to make EF (5 or 6) create the database accordingly to this code
class Program
{
static void Main(string[] args)
{
Person parent = new ResponsablePerson();
parent.Name = "Father";
Person child = new Person();
child.Name = "Child";
child.Parent = parent;
using (PersonContext pc = new PersonContext())
{
pc.Persons.Add(parent);
pc.Persons.Add(child);
pc.SaveChanges();
}
Console.ReadKey();
}
}
public class Person : IPerson
{
[Key]
public string Name { get; set; }
public IPerson Parent { get; set; }
public virtual void Work()
{
Console.WriteLine("How much are you payng me? Ok I'll do it!");
}
}
public class ResponsablePerson : Person
{
public override void Work()
{
Console.WriteLine("Right Now!");
}
}
public class NotResponsablePerson : Person
{
public override void Work()
{
Console.WriteLine("Oh HELL NO!");
}
}
public interface IPerson
{
string Name { get; set; }
IPerson Parent { get; set; }
void Work();
}
The thing is that the database EF creates contains only 1 column for the name of the person...

public class Person : IPerson
{
public virtual Parent Parent { get; set; }
IParent IPerson.Parent
{
get { return this.Parent; }
set
{
if (!(value is Parent)) throw new ArgumentException();
this.Parent = (Parent)value;
}
}
}
As you can see, the trick is to have two properties, one to make EF work (returning type is Parent) and the other to satisfy the interface (returning type is IParent). The trick is possible by implementing the interface in an explicit way.

Related

Cast generic class object to non-generic

I have 2 classes:
public class GenericClass<T>
{
public T Item {get;set;}
}
public class StringClass
{
public string Item {get;set;}
}
now i have a GenericClass object and i need to cast it to StringClass object:
var genericObj = new GenericClass<string>();
var stringObj = (StringClass)genericObj; // <---
How to cast / convert from generic class to specific one?
You can't cast one type to the other because the types are unrelated.
You could, however, define a conversion operator:
public class StringClass
{
public string Item { get; set; }
public static explicit operator StringClass(GenericClass<string> generic)
=> new StringClass { Item = generic.Item };
}
Which would allow this syntax:
var genericObj = new GenericClass<string>();
var stringObj = (StringClass)genericObj;
You can't. You would need common inherited type or implement an interface.
With inheritance:
public class GenericClass<T>
{
public T Item {get;set;}
}
public class StringClass : GenericClass<string>
{
}
if your really need it, you can do this way for examle
var stringObj = new StringClass(genericObj);
public class StringClass
{
public string Item { get; set; }
public StringClass(GenericClass<string> genericClass)
{
Item=genericClass.Item;
}
public StringClass(){}
}
or this is more flexible
public interface IGenericClass<T>
{
public T Item { get; set; }
}
public class GenericClass<T>:IGenericClass<T>
{
public T Item { get; set; }
}
public class StringClass
{
public string Item { get; set; }
public StringClass(IGenericClass<string> genericClass)
{
Item=genericClass.Item;
}
public StringClass(){}
}
Using this answer:
var genericObj = new GenericClass<string>();
var stringObj = (StringClass)Convert.ChangeType(genericObj, typeof(StringClass));
Finally i solved using ICloneable,
Here i have a base class named GenericClass, a generic class named GenericClassT, and a class named StringClass.
Inheritance is:
GenericClass <- GenericClassT <- StringClass
Using ICloneable implementation on GenericClass and GenericClassT, adding a CreateObject and CopyTo methods i reach the final goal:
var genericObj = new GenericClass<string>();
var stringObj = (StringClass)genericObj.Clone<StringClass>();
class definitions:
public class GenericClass: ICloneable
{
public string Id {get;set;}
protected virtual ApiRequestResult CreateObject()
{
return new GenericClass();
}
protected virtual void CopyTo(GenericClass obj)
{
obj.Id = Id;
}
public virtual object Clone()
{
var obj = CreateObject();
CopyTo(obj);
return obj;
}
public virtual object Clone<T>() where T: GenericClass
{
var obj = (GenericClass)Activator.CreateInstance(typeof(T));
CopyTo(obj);
return obj;
}
}
public class GenericClass<T>: GenericClass
{
public T Data {get; set;}
protected override GenericClass CreateObject()
{
return new GenericClass<T>();
}
protected override void CopyTo(GenericClass obj)
{
base.CopyTo(obj);
((GenericClass<T>)obj).Data = Data;
}
}
public class StringClass: GenericClass<string>
{
}

Generic type parameters C# - How to generic class return type

Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();

C# generics with inheritance

My problem is for some reason, I can't use derived class as the base when I pass it through a generic.
Let's suppose the below code to describe the idea
public class Person
{
public virtual bool IsGood { get; }
}
public class GoodPerson : Person
{
public override bool IsGood { get; } = true;
}
public class BadPerson : Person
{
public override bool IsGood { get; } = false;
}
public class Case<T>
{
public T PersonType { get; set; }
}
public class TypeReflector
{
public Person Reflect(Case<Person> person)
{
if (person.PersonType.IsGood)
return (GoodPerson)person.PersonType;
return (BadPerson)person.PersonType;
}
}
and called as below:
var reflector = new TypeReflector();
var result = reflector.Reflect(new Case<GoodPerson>());
why the method Reflect can't be called with Case<GoodPerson>.
but it possible without the Case as below:
public Person Reflect(Person person)
{
if (person.IsGood)
return (GoodPerson)person;
return (BadPerson)person;
}
Since Case<Person> is not the same type as Case<GoodPerson>
Much like..
Case<int> is not the same type like Case<string>
Your reflector expected a strong type Case<Person> but you're providing it a different strong type Case<GoodPerson> (so this is like providing Case<string> to a method which expects Case<int>)
To make it work, make your reflector accept Case where T is a person or derived class of a person like this:
public class TypeReflector
{
public Person Reflect<T>(Case<T> person) where T:Person
{
return person.PersonType;
}
}
But below is what I think you really want to achieve, getting an instance of a type based on properties supplied in descriptor type. A type Person once instantiated cannot be "elevated" to GoodPerson instance without another new keyword somewhere.. (btw, the opposite is possible, creating a GoodPerson and casting to the more basic Person class)
using System;
namespace ConsoleApp25
{
class Program
{
static void Main(string[] args)
{
var personDescriptor = new PersonDescriptor { IsGood = true };
var resultPerson = personDescriptor.CreateInstance();
Console.WriteLine(resultPerson.IsGood);
Console.WriteLine(resultPerson.GetType().Name);
Console.ReadLine();
}
}
public class PersonDescriptor
{
public bool IsGood { get; set; }
public Person CreateInstance()
{
if (IsGood)
return new GoodPerson(); //create new instance!
return new BadPerson(); //create new instance!
}
}
public abstract class Person
{
public abstract bool IsGood { get; }
}
public class GoodPerson : Person
{
public override bool IsGood { get; } = true;
}
public class BadPerson : Person
{
public override bool IsGood { get; } = false;
}
}

Common base class initialization

Take the scenario
BaseA -> SubB -> SubSubC
Explanation: SubSubC class inherits SubB class. The SubB class inherits BaseA class
BaseA -> SubD -> SubSubE
Explanation: SubSubE class inherits SubD class. The SubB class inherits BaseA class
So..on..
So there are many class that has its grand parent class as BaseA . The BaseA class has some properties that are common to all the methods. ex: CustomerID, LastLogin, UniqueName etc.
This is how the class is designed in the service which I'm consuming.
My doubt is While calling the service methods, all the methods would expect a parameter of any SubSub class. Can anyone please tell me, is there any way if I could assign values to the properties of the BaseA in one place so that while creating the SubSub objects I did not need to fill the base properties each time?
I'm using C# as my language.
Code:
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
public void SendRequestToService1()
{
(new MyServiceObject()).ServiceMethod1(new SubSubC());
}
public void SendRequestToService2()
{
(new MyServiceObject()).ServiceMethod2(new SubSubE());
}
}
In the above code, in SendRequestToService1 and SendRequestToService2 , i need to initialise the base class properties CustomerId and UniqueName.
Ex:
(new SubSubC(){ CustomerId=2, UniqueName="XXBB" });
If there are many methods, I need to initialize these properties each time for their respective classes. Is there a way I can initialize the base properties CustomerId and UniqueName in one place so that the inheriting classes(SubSubC,SubSubE here) no need to initialize when their objects are created?
Are you looking for the following functionality?
//dummy class replacing the service object and it's methods
public class MyServiceObject
{
public void ServiceMethod1(SubSubC param)
{ }
public void ServiceMethod2(SubSubE param)
{ }
}
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
//declare the SubSub objects
//SubSubC subSubC;
//SubSubE subSubE;
BaseA baseA;
public MyMain()
{
//assign the values to each class in the MyMain contrsuctor
baseA = new BaseA { CustomerId = 2, UniqueName = "XXBB" };
}
public void SendRequestToService1()
{
var subSub=new SubSubC();
(new MyServiceObject()).ServiceMethod1(Initialize(subSub));
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
(new MyServiceObject()).ServiceMethod2(Initialize(subSub));
}
private T Initialize<T>(T subSub) where T:BaseA
{
subSub.CustomerId = baseA.CustomerId;
subSub.UniqueName = baseA.UniqueName;
return subSub;
}
}
class Program
{
static void Main(string[] args)
{
MyMain myMain = new MyMain();
myMain.SendRequestToService1();
myMain.SendRequestToService2();
}
}
Are you asking about calling base constructors? If so:
class SubSubC : SubB
{
public object CProperty { get; private set; }
public SubSubC(object cProperty, string bProperty, int id) : base(bProperty, id)
{
CProperty = cProperty;
}
}
class SubB : BaseA
{
public string BProperty { get; private set; }
public SubB(string bProperty, int id) : base(id)
{
BProperty = bProperty;
}
}
class BaseA
{
public int ID { get; private set; }
public BaseA(int id)
{
ID = id;
}
}
Or are you asking about initializing objects in a method? If so (assume the setters are public in the following code, unlike in the preceding):
void SetSubSubCProperties(SubSubC c, object cProperty, string bProperty, int id)
{
c.CProperty = cProperty;
SetSubBProperties(c, bProperty, id);
}
void SetSubBProperties(SubB b, string bProperty, int id)
{
b.BProperty = bProperty;
SetBaseAProperties(b, id);
}
void SetBaseAProperties(BaseA a, int id)
{
a.ID = id;
}
Ok, Alex Filipovici's answer, it looks like you want to initialize an instance of a derived class by copying the base class properties from an instance of a different derived class. In that case, to reduce the duplication in Alex's answer, you can do this:
void Initialize(BaseA source, BaseA target)
{
target.CustomerID = source.CustomerID;
target.UniqueName = source.UniqueName;
}
Then, to modify his example:
public void SendRequestToService1()
{
var subSub = new SubSubC();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod1(subSub);
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod2(subSub);
}
Not sure I understand your question.
public class A {
public int ID { get; set; }
}
public class B : A {
}
you can do B b = new B() and then b.ID = 12.
Or, if you have a method that gets a parameter of type A in your service you can change the value in the same way.
public void doSomething(A a) {
a.ID = 12;
}
and call the method with instances of B - doSomething(new B())

c# parent child design

I am designing a c# class and would like to know if my design is right.
abstract class PersonBase
{
public string Name { get; set; }
public PersonBase Parent { get; set; }
public List<PersonBase> Children { get; set; }
}
class Person : PersonBase
{
//public override List<Person> Children { get; set; }
public Person()
{
Children = new List<PersonBase>();
}
public void Add(Person child)
{
child.Parent = this;
Children.Add(child);
}
}
test code:
private void button1_Click(object sender, EventArgs e)
{
Person parent = new Person();
parent.Name = "parent";
Person child = new Person();
child.Name = "child1";
child.Add(new Person() { Name = "grandchild1" });
parent.Add(child);
}
It works as expected. I am able to access the parent children objects from anywhere in the hierarchy. My concern is it looks recursive or circular reference (can't find the right word here).
Here is what I did finally:
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public List<Person> Children { get; private set; }
public Person()
{
Children = new List<Person>();
}
public void AddChild(Person child)
{
if (child == this) { return; }
if (Children.Contains(child)) { return; }
child.Parent = this;
Children.Add(child);
}
}
Like #LukeH asked your break out of BasePerson and Person do not make sense. This will work just fine.
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public IList<Person> Children { get; private set; }
public Person()
{
Children = new List<Person>();
}
public void Add(Person child)
{
child.Parent = this;
Children.Add(child);
}
}
If you are going to have different kinds of Person then you might want to break you stuff out into an Interface if there is not inherited logic and an abstract class if you want to provide some default logic.
EDIT: Adding expressed issues from Danny
It could become a problem if you used child.Add(Me or MyParent or ancestor). Then it would be an endless loop of references. You might want to add code in the Add method to prevent improper usage so a 'Person' can not add itself or it's parents as a child.
The base class seams redundant, also, you are assuming children is not null and assigning in constructor, yet it has a public setter.
Change children's setter to private or protected and don't worry about circular reference - just mark parent property with an attribute to prevent it from being serialized.
//Declare and initialize Person a, b, c;
a.Add(c);
b.Add(c); // Now a thinks c is a child, but c does not think a is a parent!
You need some sort of validation, perhaps that c doesn't already have a parent, or set the parent/child only in a Parent.CreateChild method. Or allow it to have multiple parents.
(Also, I would declare the method AddChild, since that's what it's doing. And also pay attention to the design considerations from other commenters.)
Perhaps this:
class Person
{
public string Name { get; private set; }
public Person Parent { get; private set; }
public IList<Person> Children { get; private set; }
private Person() {} // Private constructor
public static Person CreatePersonNoParent(string name){*implementation elided*};
public Person CreateChild(string name)
{
Person child = new Person { Name=name, Parent=this };
this.Children.Add(child);
return child;
}
}

Categories

Resources