Injecting derived classes - c#

I have a problem using ValueInjecter for derived classes:
public class A
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class B : A
{
public int Age { get; set; }
}
public static void main()
{
var b = new B()
{
Id = Guid.NewGuid(),
Name = "Test!",
Age = 47
};
var a = new A();
a.InjectFrom(b);
}
Injecter does not seem to copy the properties of the derived class.
I then tried to use the Clone convention and debugged the different calls to the methods, but I could not even see calls for the properties of the derived class. Only the properties directly on class A were called.
What am I doing wrong?
Best regards,
Andreas Kroll

Related

Overriding a base virtual property with a derived type is null when passing to JsonResult

I have 2 base classes which 1 for search criteria and other 1 for search results.
I also have 2 derived classes for User object versions of both of those.
When I put a breakpoint in the controller action I can see all properties are populated as I've hardcoded.
When I call this action directly in the browser, each of my derived object properties is null.
I'm guessing the JSON serialization is not able to tell the difference from the base class to the derived one.
Is there a way to solve this?
public class BaseSearchCriteria
{
public int Page { get; set; }
public int RecordsPerPage { get; set; }
}
public class BaseSearchResults
{
public int TotalResults { get; set; }
public virtual BaseSearchCriteria SearchCriteria { get; set; }
}
public class UserSearchCriteria : BaseSearchCriteria
{
public string Username { get; set; }
}
public class UserSearchResults : BaseSearchResults
{
public new UserSearchCriteria SearchCriteria { get; set; }
}
public JsonResult Search(UserSearchCriteria model)
{
var viewModel = new UserSearchResults
{
SearchCriteria = new UserSearchCriteria
{
Page = 1,
RecordsPerPage = 15
}
};
viewModel.TotalResults = 100;
return Json(viewModel, JsonRequestBehavior.AllowGet);
}
Maybe good way to deal with it is to use generics as Daniel A. White propose.
Sample gist here.

Initialize base class’s fields in subclass constructor in C#

I have a base class with three field, but instead of initializing its field the normal way like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
public ParentClass(string Name, string Family, string Address)
{
this.Name = Name;
this.Family = Family;
this.Address = Address;
}
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(string Name, string Family, string Address, int StudentID, int StudentScore)
: base(Name, Family, Address)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass("John", "Greene", "45 Street", 76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I’ve initialized the fields in the ChildClass constructor without explicitly calling the base class constructor like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(int StudentID, int StudentScore)
{
Name = "John";
Family = "Greene";
Address = "45 Street";
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass(76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I know I could have initialized the parent class’s field in the parent class itself and this is a bogus example, but I was wondering if it is considered a good practice to do something like that in real life and more complex situations, is there any reason why I shouldn’t do something like this? as to not explicitly call the base class constructor?
Edit: I'm more concerned about not explicitly call the base class constructor and initializing it in subclass part, so I've edited the last part that mentioned the fields being exposed out.
As you've already seen, the fields are already "exposed". Your could still get to those variables from the derived class in the first example.
As to not using a base class constructor being good practice, I would say not. By only having a parameterized base class constructor, you are making sure that future implementers of that class initialize the base class properties. For example, in your second I could write:
public ChildClass(int StudentID, int StudentScore)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
With no errors. Other than that there are very few differences between your samples.

Castle ActiveRecord BelongsTo with NotNull=true not-null Exception

I'm having the a problem when trying to persist a many to one relationship using Castle ActiveRecord and I hope someone has a better idea than me with this, the idea is to save a single object with a list of dependant objects in a single Save().
I have these classes:
[ActiveRecord("SomeClass")
public class SomeClass : ActiveRecordValidationBase<SomeClass>
{
[PrimaryKey]
public virtual long Id { get; set; }
[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = false)]
public virtual IList<AnotherClass> SomeObjects { get; set; }
}
[ActiveRecord("AnotherClass")
public class AnotherClass : ActiveRecordValidationBase<AnotherClass>
{
[PrimaryKey]
public virtual long Id { get; set; }
[Property(NotNull = true, Unique = true, Length = 70)]
public string Something { get; set; }
[BelongsTo("SomeId", NotNull = true)]
public virtual SomeClass Parent { get; set; }
}
What I want to do is something like this
var someClass = new SomeClass
{
SomeObjects = new List<AnotherClass>
{
new AnotherClass
{
Something = "Hello"
}
}
};
someClass.Save();
But I get this error:
Hibernate.PropertyValueException: not-null property references a null or transient value
Is there a way I could do that without setting a reference to the parent to every object before calling save?
Thanks!
you have to override BeforeSave and/or Save in your class SomeClass
public virtual void Save()
{
using(Transaction t = new Transaction())
{
foreach(AnotherClass a in this.SomeObjects??new AnotherClass[]{})
{
a.Parent = this;
a.Save();
}
base.Save();
}
}
Greetings
Juy Juka

c# Access specific class with Enum GetName

RootObject.cs
public class RootObject
{
public Class1 Class1 { get; set; }
public Class2 Class2 { get; set; }
public Class3 Class3 { get; set; }
}
Class1.cs (Class2, Class3, ....)
public class Class1
{
public string name { get; set; }
public string surname { get; set; }
}
Enum.cs
public enum Classes
{
Class1,
Class2,
Class3
}
MyFunction.cs
nItemCount = Enum.GetNames(typeof(Classes)).Length; /* equal to 3 */
for (i=0 ; i < nItemCount; i++)
{
string name = RootObject.(Enum.GetName(typeof(Classes), i)).name;
}
I want to get the name value of Class1, Class2, Class3, etc. like a method above.
I wish I could explain my problem.
I need a solution for accessing all classes in a loop with the enum value.
Can anyone please help ?
You will have to change your code to be like below. Note I have used Classes as datatype for the Property.
public class RootObject
{
public Classes ClassProp { get; set; }
}
public enum Classes
{
Class1,
Class2,
Class3
}
And then you can access the properties by using following code. You will have to instantiate the class and then access the property as they are Object level properoties and not static. Also, note that you will have to set the properties to get the appropriate enum value.
RootObject rootObj = new RootObject();
rootObj.ClassProp = Classes.Class2;
var class2 = rootObj.ClassProp;
If your classes share common members, either move those to a common base class or let the classes implement a common interface (or both).
public abstract class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class Customer : Person
{
public Address DeliveryAddress { get; set; }
}
public class Employee : Person
{
public string Profession { get; set; }
}
Then, instead of creating individual properties for each the classes, add them to an array and use the enum values as index:
public enum PersonType
{
Customer = 0,
Employee = 1,
Supplier = 2
}
public class RootObject
{
Person[] _persons = new Person[] {
new Customer(),
new Employee(),
new Supplier()
};
public Person[] Persons { get { return _persons; } }
}
Now you can access the persons easily with
foreach (PersonType personType in (PersonType[])Enum.GetValues(typeof(PersonType))) {
Person p = rootObject.Persons[(int)personType];
string name = p.Name;
string surname = p.Surname;
// ...
}
First, if all of your types Class1, Class2, Class3, ..., ClassWhatNot share same property definitions, it is better to move these same property definitions into a common BaseClass which the aforementioned classes will inherit from.
class BaseClass
{
public string Name { get; set;}
}
class Class1 : BaseClass
{
...
}
class Class2 : BaseClass
{
...
}
//... do the definition of Class3 in the same way
Implement the RootClass as follows (note that i changed the names a bit to make it clearer how things work):
class RootClass
{
public enum PropertyEnum
{
propClass1,
propClass2,
propClass3
}
public Class1 propClass1 { get; set; }
public Class2 propClass2 { get; set; }
public Class3 propClass3 { get; set; }
public BaseClass GetPropertyByEnum(RootClass.PropertyEnum enumValue)
{
PropertyInfo pi = typeof(RootClass).GetProperty(enumValue.ToString());
return pi.GetValue(instance, null) as BaseClass;
}
}
With the method GetPropertyByEnum you can easily do:
RootClass rootObj = ...create/get the root object
foreach(RootClass.PropertyEnum enumValue in Enum.GetValues(typeof(RootClass.PropertyEnum))
{
BaseClass b = rootObj.GetPropertyByEnum(enumValue);
if (b != null) Console.Out.WriteLine("{0}.name = {1}", enumValue.ToString(), b.Name);
}
Note, that when not using a common base class (such as BaseClass in my example), GetPropertyByName could only return references of type Object. In such a case you would need to know how to cast the returned object to the appropriate type, which would make the whole endeavour of accessing properties by enum mostly pointless...

Make generic object instantiation more generic

I've got this piece of code to create new objects in a generic way:
var user = User.Create<User>(c => c.Name = "321X");
What I don't like about it is the fact I need to pass the 'generic notation' <T> for every create call. After all I create an object that I'm already referring to...
The code behind this current functionality is:
public class User : CreateBase
{
public string Name { get; set; }
}
public abstract class CreateBase
{
public DateTime CreateDate { get; set; }
public Guid Guid { get; set; }
public static T Create<T>(Action<T> init) where T : CreateBase, new()
{
T obj = new T();
obj.Guid = Guid.NewGuid();
obj.DateTime = DateTime.Now;
init(obj);
return obj;
}
}
Is it possible (and how) to refactor my code to this, to create an object?
var user = User.Create(c => c.Name = "321X");
Thanks!
Define the generic argument on the class level:
public abstract class CreateBase<T> where T : CreateBase<T> , new()
{
public static T Create(Action<T> init)
{
//...
}
}
public class User : CreateBase<User>
{
public string Name { get; set; }
}
Then you can write var user = User.Create(c => c.Name = "321X");
Otherwise the compiler cannot infer the type for your Create method without specifying the type argument.
You were not very far. Try this modification:
public abstract class CreateBase<T> where T : CreateBase<T> , new()
{
public DateTime CreateDate { get; set; }
public Guid Guid { get; set; }
public static T Create(Action<T> init)
{
T obj = new T();
obj.Guid = Guid.NewGuid();
obj.CreateDate = DateTime.Now;
init(obj);
return obj;
}
}
public class User : CreateBase<User>
{
public string Name { get; set; }
}
EDIT: Updated the code after I tested it on my local environment. It works now.
You are doing it the wrong way. Instead of getting rid of the generic argument, get rid of (needlessly) saying User.. Instead:
CreateBase.Create<User>(...)
No more redundancies.
Besides that, calling a static member of the base class through a derived class is an anti-pattern.
A better approach would be to include this functionality in the constructor of the base class (I call it ModelBase)
public abstract class ModelBase
{
public DateTime CreateDate { get; private set; }
public Guid Guid { get; private set; }
public ModelBase()
{
Guid = Guid.NewGuid();
DateTime = DateTime.Now;
}
}
public User : ModelBase
{
public User()
: base()
{
}
public User(string name)
: base()
{
Name = name
}
public string Name { get; set; }
}
Creating a user the standard way will initialize the Guid and date automatically
var user = new User { Name = "xy };
EDIT
I added a second constructor with a name parameter. I you want to force the initialization of the name, drop the first parameterless constructor.
var user = new User("xy");
If you really uncomfortable with that sintax (I, honestly, don't see much problem here)
you can do the following:
public class User : CreateBase
{
public string Name { get; set; }
public static User Create(Action<User> a)
{
return Create<User>(a); //CALL BASE CLASS GENERIC FUNCTION
}
}
After you can call it in a way you would like to do that :
var user = User.Create(c => c.Name = "321X");

Categories

Resources