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.
Related
Hi after failing with inheritance (it got complicated) I stumble onto Generics. I am new to coding in general and C# is my first language.
I have two classes CIMTDXInput, RMTTDXInput which have the same properties but those properties have slightly different members. For those same 3 properties between the two, I want to just check if they are null or not.
So I wrote this:
public static TDX2KlarfResult CheckCIMTDXInput <T> (T input, TDX2KlarfResult result) where T: CIMTDXInput, RMTTDXInput
{
if (input.ToolContext == null)
{
Logger.Warn("Missing Tool Context Skipping the file");
result.errorType = "Warning";
result.errorMessage = "Missing Tool Context";
result.errorSubject = ErrorCategory.MISSING_TOOL_CONTEXT;
result.success = false;
return result;
}
if (input.SCContext == null)
{
Logger.Warn("Missing Context Skipping the file");
result.errorType = "Warning";
result.errorMessage = "Missing Context";
result.errorSubject = ErrorCategory.MISSING_CONTEXT;
result.success = false;
return result;
}
if (input.WaferContainer == null)
{
Logger.Warn("Missing Wafer Container Skipping the file");
result.errorType = "Warning";
result.errorMessage = "Missing Wafer Container";
result.errorSubject = ErrorCategory.MISSING_WAFER_CONTAINER;
result.success = false;
return result;
}
return result;
}
However the code won't compile. I thought you can assign as many classes as you want to the "T"?
Again both classes have ToolContext, SCContext, and WaferContainer. Instead of writing a function for each, I thought it would be elegant to write one for both. I also have additional inputs in the future to add so I'd like to not need to write this function each time
The why
So when you say this:
public void MyMethod<T>(T value) where T: ClassA, ClassB
You're saying that T should be derived from both ClassA and ClassB. Now it would work in this scenario:
public class ClassA
{
public int SomeProperty { get; set; }
}
public class ClassB : ClassA
{
}
public class ClassC : ClassB
{
}
MyMethod<ClassB>(classBValue); // ClassB is a ClassB and is derived from ClassA
MyMethod<ClassC>(classCValue); // ClassC is derived from ClassB, and is indirectly derived from ClassA
But this won't work:
public class ClassA
{
public int SomeProperty { get; set; }
}
public class ClassB
{
public int SomeProperty { get; set; }
}
Because it requires a ClassC that looks like this:
public class ClassC : ClassA, ClassB
{
}
And this could will cause a compile time error because C# doesn't support multiple inheritance. That is to say that, while you can have a class derived from a class that itself is derived from another class, you can't create a class that directly derives from two classes.
The solution
What you can do is declare an interface:
public interface ISomeInterface
{
int SomeProperty { get; set; }
}
And have both the classes implement it:
public class ClassA : ISomeInterface
{
public int SomeProperty { get; set; }
}
public class ClassB : ISomeInterface
{
public int SomeProperty { get; set; }
}
Then if we change our method signature to require that the class implements our interface:
public void MyMethod<T>(T value) where T: ISomeInterface
Then within the method we can access the SomeProperty property of T:
public void MyMethod<T>(T value) where T: ISomeInterface
{
value.SomeProperty *= 2;
}
Try it online
you need to use an interface
public interface IInput
{
public string ToolContext {get;set;}
public string SCContext {get;set;}
public string WaferContainer {get;set;}
}
public class CIMTDXInput:IInput
{
public string ToolContext {get;set;}
public string SCContext {get;set;}
public string WaferContainer {get;set;}
.... another properties
}
public class RMTTDXInput:IInput
{
public string ToolContext {get;set;}
public string SCContext {get;set;}
public string WaferContainer {get;set;}
.... another properties
}
and your method should be
public static TDX2KlarfResult CheckCIMTDXInput<T>(T input, TDX2KlarfResult result) where T : IInput
or you can get without a generic in this case , would be enough
public static TDX2KlarfResult CheckCIMTDXInput(IInput input, TDX2KlarfResult result)
I have a method which takes an object as a parameter. Within that method I walk through that objects properties with reflection. Some properties are of a generic class type. I like to read a property of that generic class property, but I cannot cast it to a generic class.
public abstract class BaseClass
{
public int Id { get; set; }
}
public abstract class GenericClass<T>: BaseClass
{
public string Description { get; set; }
}
public class DerivedClassA: GenericClass<DerivedClassA>
{
public string A { get; set; }
}
public class DerivedClassB: GenericClass<DerivedClassB>
{
public string B { get; set; }
}
public class ReflectingClass: BaseClass
{
public string Code { get; set; }
public DerivedClassA DerA { get; set; }
public DerivedClassB DerB { get; set; }
}
public static void Reflecting(object obj)
{
var t = GetType(obj)
foreach (var pi in t.GetProperties())
{
if (obj.GetType().BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>)
{
var genClassObjProperty = ((GenericClass<T>)obj).Description; // Error, cannot do this at all !!!
}
}
}
What I want is for the code to walk to the properties and whatever the derived class actually is get the Description property of the GenericClass it is derived from.
I am using a generic class, because elsewhere in the code I call methods by their derived class and get the proper class type without resorting to all kinds of cast and passing types. I.e:
DerivedClassA.DoSomething()
instead of
BaseClass.DoSomething<DerivedClassA>()
or
BaseClass.DoSomething(type derivedClassType)
Take a look at this:
public static void Reflecting(object obj)
{
foreach (var pi in obj.GetType().GetProperties())
{
if (pi.PropertyType.BaseType.IsGenericType
&& pi.PropertyType.BaseType.GetGenericTypeDefinition()
== typeof(GenericClass<>))
{
var propValue = pi.GetValue(obj);
if (propValue != null)
{
var description = propValue.GetType()
.GetProperty("Description").GetValue(propValue);
Console.WriteLine(description);
}
}
}
Console.ReadKey();
}
I think this is what you need.
I have an arbitrary amount of classes, classThatInherits, anotherClassThatInherits, etc. that inherit classToBeInherited.
I then have a method, b, that needs to be able to access myValue from the classes that inherit classToBeInherited. How can I achieve this, without casting?
//This class will be inherited by other classes
public class classToBeInherited {
public bool isSomething { get; set; }
}
//This class with inherit 'classToBeInherited'
public class classThatInherits : classToBeInherited {
public int myValue { get; set; } //this needs to be accessable...
}
//...And so will this class
public class anotherClassThatInherits : classToBeInherited {
public int myValue { get; set; }
}
private class normalClass {
private void a() {
classThatInherits cti = new classThatInherits();
b(cti);
anotherClassThatInherits acti = new anotherClassThatInherits();
b(acti);
}
private void b(classToBeInherited c) {
//***
//get myValue from the classes that inherit classToBeInherited
//***
}
}
Move myValue to classToBeInherited:
public class classToBeInherited {
public bool isSomething { get; set; }
public abstract int myValue { get; set; }
}
Then in classThatInherits and anotherClassThatInherits use public override int myValue { get; set; } to implement that property.
Ofcorse, if myValue is needed in only some of the classes, then you can have virtual and not abstract property.
var a = c as anotherClassThatInherits;
if (a != null)
{
var myValue = a.myValue;
}
I don't know why you don't want to do casting, but it's very common to have code like above.
UPDATED
If you really don't want casting, you can use reflection (but you still need to know the type of anotherClassThatInherits)
var getter = typeof(anotherClassThatInherits).GetProperty("myValue").GetGetMethod();
var myValue = getter.Invoke(c, null);
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...
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