I want the following, is it possible in C#
public class BaseClass
{
public string Name {get;set;}
public DateTime Login {get;set;}
}
public class ChildA : BaseClass
{
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class childB : BaseClass
{
public string StreetAdrees{get; set;}
}
Now I want that if I create an instance of any child class Name="John" and Login "2013-12-12" or from database already set its irritating to set these attribute for every class
just like that
ChildA obj=new ChildA();
obj.Name and obj.Login already have Data
Specify constructor in base class, then create constructors in child classes which inherit from base classes constuctor like below
public class ChildA : BaseClass
{
public ChildA():base(){}
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class BaseClass
{
public BaseClass()
{
//set Data
.....
}
....
}
read more about base keyword
In the example below, children would actually point to the same instance of base
The example uses cache, but it could be anything else (session, application state, etc).
public class BaseClass
{
private string _name;
private DateTime _login;
public string Name
{
get
{
return Instance._name;
}
set
{
_name = value;
}
}
public DateTime Login
{
get
{
return Instance._login;
}
set
{
_login = value;
}
}
public static BaseClass Instance
{
get
{
// check if null, return a new instance if null etc...
return HttpContext.Current.Cache["BaseClassInstance"] as BaseClass;
}
set
{
HttpContext.Current.Cache.Insert("BaseClassInstance", value);
}
}
}
public class ChildA : BaseClass
{
public string SchoolName { get; set; }
public string ClassName { get; set; }
}
public class childB : BaseClass
{
public string StreetAdrees { get; set; }
}
testing it:
BaseClass.Instance = new BaseClass() { Login = DateTime.Now, Name = "Test" };
ChildA ch = new ChildA();
ChildA ch2 = new ChildA();
childB chb = new childB();
Response.Write(ch.Login.Millisecond);
Response.Write("<BR/>");
Response.Write(chb.Login.Millisecond);
Result:
906
906
Related
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>();
I've inherited a bloated project that uses a huge class as an in-memory database:
public class Database
{
public class Parameter1
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter1Value> paramValues;
}
public class Parameter2
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter2Value> paramValues;
}
public class Parameter1Value
{
public string Value { get; set;}
public Parameter parameter { get; set;}
}
public class Parameter2Value
{
public int Value { get; set;}
public Parameter2 parameter { get; set;}
}
public List<Parameter1> parameter1List { get; set; }
public List<Parameter2> parameter2List { get; set; }
}
I am creating a generic method that creates instances of Parameter1 or Parameter2 (see below) and should add those to their respective lists, but I don't know how to use those types to get the parameter1List or parameter2List instances from my Database class. The Database class holds only one List<T> property for each defined type. Is this possible?
This is the generic method used to create instances:
public static Database Add<T>(this Database database, string code, string label) where T : new()
{
T itemToCreate = (T)Activator.CreateInstance(typeof(T));
itemToCreate.Code = code;
itemToCreate.Label = label;
var listForItem = database.GetList<T>; // This is the missing functionality
listForItem.Add(itemToCreate);
return database;
}
Here is a solution using interfaces and generic constraints.
Create an interface to represent a generic parameter class and add members to the interface as required:
public interface IParameter { ... }
And an interface to represent a list of parameters:
public interface IParameterList<TParameter> where TParameter : IParameter
{
List<TParameter> ParameterList { get; set; }
}
Have the Database and Parameter classes implement these new interfaces:
public class Parameter1 : IParameter
public class Parameter2 : IParameter
public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }
...
}
Add a where TParameter : IParameter constraint to your generic Parameter factory function, and have the factory function require an argument of type IParameterList<TParameter> which is an instance of the Database class. This satisfies the compiler that the Database class owns a list of TParameter. Now we just do db.ParameterList.Add(r) to add our new parameter to the correct list.
public static TParameter CreateParameter<TParameter>(IParameterList<TParameter> db) where TParameter : IParameter, new()
{
var r = new TParameter(); // This is the generic function you mentioned. Do stuff here to create your Parameter class.
db.ParameterList.Add(r); // Add the newly created parameter to the correct list
return r;
}
Code dump (full working version after I picked up your edit which added the generic factory function):
public class Parameter1 : IParameter
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter1Value> paramValues;
}
public class Parameter2 : IParameter
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter2Value> paramValues;
}
public class Parameter1Value
{
public string Value { get; set; }
public Parameter parameter { get; set; }
}
public class Parameter2Value
{
public int Value { get; set; }
public Parameter2 parameter { get; set; }
}
public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
// Note: Setters for the List properties probably not needed here or in IParameterList as with the following code we instantiate them at class construction time and, in this MCVE at least, there are no further assignments
public List<Parameter1> parameter1List { get; set; } = new List<Parameter1>();
public List<Parameter2> parameter2List { get; set; } = new List<Parameter2>();
List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }
public static TParameter Add<TParameter>(IParameterList<TParameter> db, string code, string label) where TParameter : IParameter, new()
{
var itemToCreate = new TParameter();
itemToCreate.Code = code;
itemToCreate.Label = label;
db.ParameterList.Add(itemToCreate); // Add the newly created parameter to the correct list
return itemToCreate;
}
}
public interface IParameter
{
string Code { get; set; }
string Label { get; set; }
}
public interface IParameterList<TParameter> where TParameter : IParameter
{
List<TParameter> ParameterList { get; set; }
}
// Testing:
void Main()
{
var db = new Database();
Database.Add<Parameter1>(db, "hello", "hello2");
Database.Add<Parameter1>(db, "hello", "hello2");
Database.Add<Parameter2>(db, "hello", "hello2");
Console.WriteLine($"P1 count (should be 2): {db.parameter1List.Count()}; P2 count (should be 1): {db.parameter2List.Count}");
}
Output:
P1 count (should be 2): 2; P2 count (should be 1): 1
Here is a solution which acquires the target list using generics and reflection:
public static List<T> GetList<T>(this Database dataBase) where T : new()
{
return dataBase.GetType()
.GetProperties()
.Where(x => x.PropertyType == typeof(List<T>))
.Select(x => (List<T>)x.GetValue(dataBase))
.FirstOrDefault();
}
Credit: Michael Randall in the comments
I have multiple classes that inherit from a base class and I need to check values of this classes about I want to avoid from writing the same checks for the same properties of base class that where inherited
class baseClass
{
public int Firstname;
public string LastName;
public string ID;
}
class TypeOneAditionalInformation: baseClass
{
public string x1;
public string x2;
}
class TypeTwoAditionalInformation: baseClass
{
public int x3;
public string x4;
}
public List<ErrorGet> TypeOneTest(TypeOneAditionalInformation _type)
{
if(_type.Firstname!=null) ...
if(_type.LastName!=null) ...
if(_type.ID!=null) ...
if(_type.x1!=null) ...
if(_type.x2!=null) ...
}
public List<ErrorGet> TypeTwoTest(TypeTwoAditionalInformation _type)
{
if(_type.Firstname!=null) ...
if(_type.LastName!=null) ...
if(_type.ID!=null) ...
if(_type.x3!=null) ...
if(_type.x4!=null) ...
}
I want to avoid from doing twice same checks on the same base type properties:
if(_type.Firstname!=null) ...
if(_type.LastName!=null) ...
if(_type.ID!=null) ...
what is the best practice for it ?
Create a function to check for base type errors and call that function inside other two types.
Something like:
public List<ErrorGet> BaseClassTest(baseClass _type)
{
if(_type.Firstname!=null) ...
if(_type.LastName!=null) ...
if(_type.ID!=null) ...
}
Then call it from other two ...
public List<ErrorGet> TypeTwoTest(TypeTwoAditionalInformation _type)
{
BaseClassTest(_type);
..
..
if(_type.ID!=null) ...
if(_type.x3!=null) ...
if(_type.x4!=null) ...
}
Consider a validation framework to do such things and you'll save a lot of time.
For example, model validation being used in ASP.NET MVC and ASP.NET Web API can be used as a standalone validator.
Imagine there's a class A which has a Text property and you want to it as not null:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public class A
{
[Required]
public string Text{get;set;}
}
public class Program
{
public static void Main()
{
List<ValidationResult> errors = new List<ValidationResult>();
if(Validator.TryValidateObject(new A(), null, errors))
{
// Do stuff if object validates
}
}
}
In your case, your base class can run the validator for this:
public class baseClass
{
// Note I've switched your class fields to auto-properties
[Required]
public int Firstname { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string ID { get; set; }
protected virtual bool Validate()
{
List<ValidationResult> results = new List<ValidationResult>();
// Running it for "this" executes the validator for the most derived
// class, so this includes ALL properties (from the base class to
// the most derived one!
return Validator.TryValidateObject(this, null, results);
}
}
This way, you can call Validate in derived classes and all properties will be automatically checked to be filled with some value, even properties from derived classes (you get an all-in-one solution).
There're many other validation attributes than you can apply to your properties (check them in MSDN System.ComponentModel.DataAnnotations namespace documentation).
In that case, use a parametrized constructor to initialize the members in base class using constructor initializer. Should be like below
class baseClass
{
public string Firstname;
public string LastName;
public string ID;
public baseClass(string fn, string ln, string id)
{
this.Firstname = fn;
this.LastName = ln;
this.ID = id;
}
}
class TypeOneAditionalInformation: baseClass
{
public string x1;
public string x2;
public TypeOneAditionalInformation(string fn, string ln,
string id, string x1, string x2) : base(fn, ln, id)
{
this.x1 = x1;
this.x2 = x2;
}
}
This is where polymorphism really becomes awesome!
What you should be doing is in your base class, declaring TypeTest as virtual. Then you should override it in each of your inherited classes, adding the additional functionality. Here is an example:
class BaseClass
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual void TypeTest()
{
Console.WriteLine(FirstName != null ? "FirstName is NOT NULL!" : "FirstName IS NULL!");
Console.WriteLine(LastName != null ? "LastName is NOT NULL!" : "LastName IS NULL!");
}
}
class TypeOneAditionalInformation : BaseClass
{
public string X1 { get; set; }
public string X2 { get; set; }
public override void TypeTest()
{
base.TypeTest();
Console.WriteLine(X1 != null ? "X1 is NOT NULL!" : "X1 IS NULL!");
Console.WriteLine(X2 != null ? "X2 is NOT NULL!" : "X2 IS NULL!");
}
}
class TypeTwoAditionalInformation : BaseClass
{
public string X3 { get; set; }
public string X4 { get; set; }
public override void TypeTest()
{
base.TypeTest();
Console.WriteLine(X3 != null ? "X3 is NOT NULL!" : "X3 IS NULL!");
Console.WriteLine(X4 != null ? "X4 is NOT NULL!" : "X4 IS NULL!");
}
}
What this will allow you to do is just execute TypeTest without needing to worry about the types or properties. Here is an example:
var baseClass = new BaseClass();
var type1 = new TypeOneAditionalInformation();
var type2 = new TypeTwoAditionalInformation();
baseClass.FirstName = "Joe";
baseClass.LastName = "Miller";
type1.FirstName = "Rachel";
type1.LastName = "Miller";
type1.X1 = "72";
type2.FirstName = null;
type2.LastName = "Miller";
type2.X4 = "99";
var list = new List<BaseClass> {baseClass, type1, type2};
foreach (BaseClass obj in list)
{
Console.WriteLine();
// Here is where polymorphism is magic!
obj.TypeTest();
Console.WriteLine();
}
What's happening here is your program is dynamically called the appropriate TypeTest function at runtime. If obj is a BaseClass type, then your program will automagically know to call the TypeTest method inside BaseClass. Similarly, if obj is a TypeOneAditionalInformation class then your program will know to call the TypeTest inside that class.
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...
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())