Constraints and implicite operators - c#

I have three classes A,B and C,
some properties are in all three classes, some not
public class A
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int xxx {get; set} // only in class A
public int yyy{get; set} // only in class A
...
}
public class B
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int aaa {get; set} // only in class B
public int bbb {get; set} // only in class B
...
}
public class C
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int kkk {get; set} // only in class C
public int ppp {get; set} // only in class C
...
}
I want to call the Execute method of class XYZ ...
public class XYZ
{
public override Execute<T>() where T: Generic_T, new()
{
T abc = new T();
...
Debug.WriteLine(abc.Firstname + ”, “ + abc.Lastname + “, “ + abc.ID);
}
}
... with all three classes,like:
XYZ x1 = new XYZ();
XYZ.Execute<A>();
XYZ x2 = new XYZ();
XYZ.Execute<B>();
XYZ x3 = new XYZ();
XYZ.Execute<C>();
My idea doesn’t work:
public class Generic_T
{
public static implicit operator A(Generic_T x)
{
return (A)x.MemberwiseClone();
}
}
Where is the mistake?
Thanks in advance!

Mistakes:
What is CloneMemberwise() ?
If you meant MemberwiseClone(), you can't call it there. It is a protected member.
You cannot call properties on a type. Here: T.Firstname, T.Lastname, etc.
It is Debug, not Degub.
You do not pass a value/reference in to the Execute method.
Neither A, B or C derives from Generic_T, so the constraint on the Execute method will fail.
Class names do not end with (). You had class A() which I re-edited already.
A or any class cannot be automagically converted to Generic_T.
You should be using inheritance, I suspect Generic_T should be a base class.
You do not have a specific question
Possible suggestion:
public abstract class Generic_T
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
}
public class A : Generic_T
{
public int xxx {get; set} // only in class A
public int yyy{get; set} // only in class A
...
}
public class B : Generic_T
{
public int aaa {get; set} // only in class B
public int bbb {get; set} // only in class B
...
}
public class C : Generic_T
{
public int kkk {get; set} // only in class C
public int ppp {get; set} // only in class C
...
}
Also there is not reason to convert any of the derived classes to Generic_T as they as an instance of Generic_T already.
All of this information is normally explained in most introductory texts for C#/.NET. Failure to understand them, will make your life miserable.

Don't know why do you need Generic_T in your code.
To force Execute work you need to implement following interface
interface IFoo
{
int ID {get; set;}
string LastName {get; set;}
string FirstName {get; set;}
}
Then your execute method will look like this:
public override Execute<T>(T obj) where T: new(), IFoo
{
Debug.WriteLine(obj.Firstname + ”, “ + obj.Lastname + “, “ + obj.ID);
}

Related

One select list consisting of two classes

I have 3 classes
public class A
{
public decimal id {get; set;}
public virtual B? BNavigation {get; set;};
public virtual C? CNavigation {get; set;};
}
public class B
{
public int id {get; set;}
public string title {get; set;}
[...]
}
public class C
{
public int id {get; set;}
public string title {get; set;}
[...]
}
I try example above, string concatenation, tried to do it with LINQ.
I realized that I need to do this through an auxiliary class.
And i want to make SelectList by class A
Example:
ViewData["A"] = new SelectList( A,"Id", "BNavigation.title - CNavigation.title");
How can i do it ?
I want this post to be closed, because i found block of code which decide my problem
ViewBag.PackageId = db.Packages.Where(p => p.status == "A")
.Select(p => new SelectListItem
{
Text = p.u_package_id + "-" + p.package_nme,
Value = p.u_package_id.ToString()
});

Deserializing Api Object with JSON.net

Let me explain my problem.
So I have JSON:
{"num":20, "meta":[{"id":312, "identif":{"type":true,"status":false}}}]}
I am currently grabbing the meta id field with:
var id = JsonConvert.DeserializeObject<typeObj>
(returnJSON(ApiUrl)).meta[0].id;
class to refrence:
class typeObj
{
public int num {get; set; }
public List<metatypes> meta {get; set;}
}
class metatypes
{
public int id {get; set;}
}
The issue doesn't lay here though. I am trying to get the indentif status element from meta.
I have tried putting a list in metatypes like:
class metatypes
{
public int id {get; set;}
public List<idtypes> identif {get; set;}
}
class idtypes
{
public bool type {get; set;}
public bool status {get; set;}
}
Calling it with:
var id = JsonConvert.DeserializeObject<typeObj>
(returnJSON(ApiUrl)).meta[0].identif[0].status;
But when I try this it returns
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1'
Looked around and couldn't find a direct solution to my problem.
You have an incorrect json for the desired structure:
Given classes:
class typeObj
{
public int num {get; set; }
public List<metatypes> meta {get; set;}
}
class metatypes
{
public int id {get; set;}
public List<idtypes> identif {get; set;}
}
class idtypes
{
public bool type {get; set;}
public bool status {get; set;}
}
Your json should look like (identif must be an array): (.NET Fiddle)
{"num":20, "meta":[{"id":312, "identif":[{"type":true,"status":false}]}]}
For the json in question your classes should be like this: (.NET Fiddle)
class typeObj
{
public int num {get; set; }
public List<metatypes> meta {get; set;}
}
class metatypes
{
public int id {get; set;}
public idtypes identif {get; set;}
}
class idtypes
{
public bool type {get; set;}
public bool status {get; set;}
}

Generic field type in C# entity

I have a class of several fields:
class Entity{
public int field1 {get; set;}
public int field2 {get; set;}
public int field3 {get; set;}
}
However, I want to be able to reuse this class with the other types: string or bool maybe.
But the compiler does not like if I replace public int field1 {get; set;} with public T field1 {get; set;}
What is the best way to achieve this goal?
You'll need a generic parameter on your type, like this:
class Entity<T> {
public T field1 {get; set;}
public T field2 {get; set;}
public T field3 {get; set;}
}
You can then re-use this like so:
class EntityOfInt : Entity<int> {
///field1 is an int
///field2 is an int
///field3 is an int
}
In .NET 4 and above you can use dynamic
class Entity {
public dynamic field1 {get; set;}
public dynamic field2 {get; set;}
public dynamic field3 {get; set;}
}
possible overide
class Foo : Entity {
public new string field1 {get; set;}
public new int field2 {get; set;}
//field3 is still dynamic
}
This way you can still do boxing and unboxing for both types, and have your fields exposed. If not overrwriten, they will stay dynamic. So you can have simple class syntax and possibility for multiple unconstrained templates within one class.
class above using generic template
class Entity<T1,T2,T3>
where T3: new()
{
public T1 field1 {get; set;}
public T2 field2 {get; set;}
public T3 field3 {get; set;}
}
as you can see this can quickly get out of hand,
but remember, this is not type safe as method with class Entity<T>, because dynamic fields will accept all types, and override previously used. And you will have to unbox it every time you want to use it as object.
For more information see MSDN
MSDN
You can use multiple generic types:
public class Entity<T1, T2, T3, T4>
{
public virtual T1 Field1 {get;set;}
public T2 Field2 { get; set; }
public T3 Field3 { get; set; }
public T4 Field4 { get; set; }
}
public class Derived : Entity<int, string, bool, int>
{
public override int Field1 { get; set; }
}

C# & EF 4 - Update related object in database

My classes (and tables):
class A {
public int Id {get; set;}
public string Name {get; set;}
public virtual C CField {get; set;}
}
class B {
public int Id {get; set;}
public string Name {get; set;}
public DateTime Date {get; set;}
public virtual C CField {get; set;}
}
class C {
public int Id {get; set;}
public string Name {get; set;}
}
class D {
public int Id {get; set;}
public string Title {get; set;}
public virtual A AField {get; set;}
public virtual B BField {get; set;}
}
I need update my D object. I use dependency injection so I can use repositories in controller:
A aObj = aService.GetAById(id);
B bObj = bService.GetBByName(name);
D dObj = new D()
{
Title = "MyTitle",
AField = aObj,
BField = bObj
};
dService.Update(dObj);
In each class repository I just create context as private field:
private MyContext db = new MyContext();
and I use it in every method like:
var model = db.A.Where(x=>x.Id == id);
return model;
But it can't work because both classes A and B has field with C class so I still got excepted: An entity object cannot be referenced by multiple instances of IEntityChangeTracker when I call dService.Update(dObj) (second listing).
I found that I should detach context in every method in each repositroy like this:
var model = db.A.Where(x=>x.Id == id);
db.Entry(model).State = System.Data.Entity.EntityState.Detached;
return model;
Exception was gone but now CField in aObj and bObj is always null and dObj.BField is not updated.
How can I fix that and what I'm doing wrong? I lost a few days for finding out what I should do: I even try remove private context field in repositories and in every method just use using(var db = new MyContext()) but then exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" is back.
You can't mix entities from different contexts in EF. Use ids instead.
Update models:
class A {
public int Id {get; set;}
public string Name {get; set;}
public int CFieldId {get; set;}
public virtual C CField {get; set;}
}
class B {
public int Id {get; set;}
public string Name {get; set;}
public DateTime Date {get; set;}
public int CFieldId {get; set;}
public virtual C CField {get; set;}
}
class C {
public int Id {get; set;}
public string Name {get; set;}
}
class D {
public int Id {get; set;}
public string Title {get; set;}
public int AFieldId {get; set;}
public int BFieldId {get; set;}
public virtual A AField {get; set;}
public virtual B BField {get; set;}
}
And in controller:
A aObj = aService.GetAById(id);
B bObj = bService.GetBByName(name);
D dObj = new D()
{
Title = "MyTitle",
AFieldId = aObj.Id,
BFieldId = bObj.Id
};
dService.Update(dObj);

how to implement compostion in c#

I have two classes A and B in which two properties 'prop1' and 'prop2' are common. How can I have compostion implemented. May be Class C can have these common properties. Its a has-a relationship and not is-a.
public class A {
public int Prop1{get;set;}
public int Prop2 {get; set;}
public int Prop3{get;set;}
public int Prop4 {get; set;}
}
public class B {
public int Prop1{get;set;}
public int Prop2 {get; set;}
public int Prop5{get;set;}
public int Prop6 {get; set;}
}
If I have a interface say C and have these two common properties in it would that classify as composition? Something like
inferace C {
int Prop1{get;set;}
int Prop2 {get; set;}
}
public class A : C
{
}
public class B : C
{
}
Thanks in advance.
Implementing an interface is not composition, although that would be an alternative way to avoid duplicating code.
To do this using composition, you should create a new class with Prop1 and Prop2, and have an instance of this class as a property of ClassA and ClassB.
public class CompositeKey
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
public class A
{
public CompositeKey Key { get; set; }
public int Prop3 { get; set; }
public int Prop4 { get; set; }
}
...
This is a bit more flexible than using an interface because you can assign any subtype of CompositeKey to your property at run time, but the main reason you should do it this way is because class A has a composite key, you don't want to use your class as a CompositeKey.

Categories

Resources