Adding additional properties without having to overwrite base properties - c#

I have a number of classes deriving from an abstract base class. The concrete classes are stored in a container by references to base class. The concrete classes have many properties which are used to bind to pages in a FixedDocument.
I want to add aditional properties to the concrete classes at runtime which will also bind to the FixedDocument pages. I looked into the decorator pattern but it seems i have to override all the concrete class properties in the decorator class for them to be visible. Is there a way of adding a wrapper that is derived from the concrete class that inherits the values of the base properties as follows:
class BaseClass
{
public string Name { get; set; }
}
class ConcreteClass : BaseClass
{
public int MyProperty { get; set; }
}
class ConcreteClassWrapper : ConcreteClass
{
public int AdditionalProperty { get; set; }
public ConcreteClassWrapper(ConcreteClass cc)
{
base = cc;
}
}
private static void RunTime()
{
List<BaseClass> list = new List<BaseClass>();
ConcreteClass cc = new ConcreteClass()
{
Name = "Original",
MyProperty = 5
};
list.Add(cc);
cc = new ConcreteClassWrapper(cc)
{
AdditionalProperty = 10
};
}
Obviously i cant just set 'base = cc'. Is there anyway to achieve this?

Can you modify ConcreteClass so that it has an additional constructor:
class ConcreteClass : BaseClass
{
public int MyProperty { get; set; }
public ConcreteClass(ConcreteClass copy)
{
this.MyProperty = copy.MyProperty;
}
}
class ConcreteClassWrapper : ConcreteClass
{
public int AdditionalProperty { get; set; }
public ConcreteClassWrapper(ConcreteClass cc)
base(cc)
{
}
}

You can imagine the wrapper class to be defined like this
class ConcreteClassWrapper : ConcreteClass
{
public string Name { get; set; } // Inherited from BaseClass
public int MyProperty { get; set; } // Inherited from ConcreteClass
public int AdditionalProperty { get; set; }
}
It contains all the members declared in the all the base classes, since it inherits them.
You can create a new instance like this (assuming that you have a default constructor)
var wrapper = new ConcreteClassWrapper {
Name = "xy",
MyProperty = 5,
AdditionalProperty = 7
};
However, if you want the wrapper to be a true wrapper, do not inherit from the base class
class ConcreteClassWrapper
{
private ConcreteClass _cc;
public ConcreteClassWrapper(ConcreteClass cc)
{
_cc = cc;
}
public string Name { get { return _cc.Name; } set { _cc.Name = value; } }
public string MyProperty{ get { return _cc.MyProperty; } set { _cc.MyProperty = value; } }
public int AdditionalProperty { get; set; }
}

Related

C# Interface Inheritance override

I confused about a base interface property hiding, what is still needed in the implemented class, can somebody tell me why?
The goal will be the 'EndClass' only hide/override the 'IClassValue Value', and not need to implement the already hide 'IBaseClassValue Value'.
Thanks!
public interface IBaseClassValue { }
public interface IClassValue : IBaseClassValue { }
public class ClassValue : IClassValue { }
//-----------------------------------------
public interface IEndClassBase
{
IBaseClassValue Value { get; set; }
}
public interface IEndClassBaseChild : IEndClassBase
{
new IClassValue Value { get; set; }
}
//-----------------------------------------
public abstract class EndClassAbs<TValue>
{
TValue Value { get; set; }
}
public class EndClass : EndClassAbs<ClassValue>, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
//IBaseClassValue IEndClassBase.Value { get; set; } //-> Why need here the base member while already hide in the 'IEndClassBaseChild' interface
}
If I use somekind of shadow class '_EndClass' then inherit from it, the 'EndClass' could hide/override the 'ClassValue'. I still don't know why this can not do in one step.
public class _EndClass : EndClassAbs<ClassValue>, IEndClassBase
{
public new IBaseClassValue Value { get; set; }
}
public class EndClass : _EndClass, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
}

How do I create a generic List using abstract class?

I have a Json class "GetAllDevices()". My JSON response consists of an Array/List of objects, where each object has the below common properties.
public class GetAllDevices
{
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("actions")]
public Action[] Actions { get; set; }
public class Action
{
public string _id { get; set; }
public Action_Def action_def { get; set; }
}
public class Action_Def
{
public string _id { get; set; }
public string name { get; set; }
}
}
I want to create 2 generic lists containing all the above properties based on its "type".
lstfoo1 List contains all the properties(_id, name type and actions) where type="foo1". Similarly, lstfoo2 is a List which contains the above properties where type="foo2".
What I have done so far:
string strJson=getJSON();
Foo1 lstfoo1=new Foo1();
Foo2 lstfoo2=new Foo2();
List<Foo1> foo1list= lstfoo1.GetDeviceData(strJson);
List<Foo2> foo2list = lstfoo2.GetDeviceData(strJson);
public class AllFoo1: GetAllDevices
{
}
public class AllFoo2: GetAllDevices
{
}
public abstract class HomeDevices<T>
{
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1{ get; set; }
public List<AllFoo2> lstfoo2{ get; set; }
public abstract List<T> GetDeviceData(string jsonResult);
}
public class Foo1: HomeDevices<AllFoo1>
{
public Foo1()
{
type = "foo1";
}
public override List<AllFoo1> GetDeviceData(string jsonResult)
{
var lst =Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo1>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
public class Foo2: HomeDevices<AllFoo2>
{
public Foo2()
{
type = "foo2";
}
public override List<AllFoo2> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo2>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
My question is, is there an easier way to do this using abstract classes? Can I directly convert my "GetAllDevices" class into an abstract class and inherit it and deserialize into it and create a generic list?
This should help, if I understand your problem correctly. Let me know if you have questions or it doesn't work as you need. I put this together really quickly without testing.
The way the Type property is defined could be improved but I left it as you had it.
public class MyApplication
{
public void DoWork()
{
string json = getJSON();
DeviceTypeOne foo1 = new DeviceTypeOne();
DeviceTypeTwo foo2 = new DeviceTypeTwo();
IList<DeviceTypeOne> foo1Results = foo1.GetDeviceData(json); // calls GetDeviceData extension method
IList<DeviceTypeTwo> foo2Results = foo2.GetDeviceData(json); // calls GetDeviceData extension method
}
}
// implemented GetDeviceData as extension method of DeviceBase, instead of the abstract method within DeviceBase,
// it's slightly cleaner than the abstract method
public static class DeviceExtensions
{
public static IList<T> GetDeviceData<T>(this T device, string jsonResult) where T : DeviceBase
{
IEnumerable<T> deviceDataList = JsonConvert.DeserializeObject<IEnumerable<T>>(jsonResult);
IEnumerable<T> resultList = deviceDataList.Where(x => x.Type.Equals(typeof(T).Name));
return resultList.ToList();
}
}
// abstract base class only used to house common properties and control Type assignment
public abstract class DeviceBase : IDeviceData
{
protected DeviceBase(string type)
{
if(string.IsNullOrEmpty(type)) { throw new ArgumentNullException(nameof(type));}
Type = type; // type's value can only be set by classes that inherit and must be set at construction time
}
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; private set;}
[JsonProperty("actions")]
public DeviceAction[] Actions { get; set; }
}
public class DeviceTypeOne : DeviceBase
{
public DeviceTypeOne() : base(nameof(DeviceTypeOne))
{
}
}
public class DeviceTypeTwo : DeviceBase
{
public DeviceTypeTwo() : base(nameof(DeviceTypeTwo))
{
}
}
// implemented GetAllDevices class as IDeviceData interface
public interface IDeviceData
{
string Id { get; set; }
string Name { get; set; }
string Type { get; }
DeviceAction[] Actions { get; set; }
}
// renamed and relocated class Action to DeviceAction
public class DeviceAction
{
public string Id { get; set; }
public DeviceActionDefinition DeviceActionDefinition { get; set; }
}
// renamed and relocated Action_Def to DeviceActionDefinition
public class DeviceActionDefinition
{
public string Id { get; set; }
public string Name { get; set; }
}
It should be simple enough to move the implementation of method GetDeviceData() to the base class.
For this to work, you will need to add a constraint on T so the compiler knows a bit more about the base type. You will also need to implement a constructor to populate the concrete type's type string you use around. This is a necessary measure to ensure the value is always populated as it is used for comparison in the method in question:
public abstract class HomeDevices<T> where T: GetAllDevices
{
public HomeDevices(string concreteType)
{
type = concreteType;
}
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1 { get; set; }
public List<AllFoo2> lstfoo2 { get; set; }
//This method is now generic and works for both.
public List<T> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
I hope that helps.

Copy properties from base class to derived class without manually mapping in C# with reflection

How can I copy properties from my base class instance to the derived class?
public class Base
{
public string BaseProperty { get; set; }
}
public class House : Base
{
public string HouseProp { get; set; }
}
I don't want to do this:
Base base = new Base() { BaseProperty = "Hello World" };
House house = new House();
house.BaseProperty = base.BaseProperty;
Base _base = new Base() { BaseProperty = "Hello World" };
House _house = new House(_base);
public class Base
{
public string BaseProperty { get; set; }
}
public class House : Base
{
public House(Base _base)
{
foreach (PropertyInfo property in _base.GetType().GetProperties())
{
PropertyInfo propinfo = _base.GetType().GetProperty(property.Name);
propinfo.SetValue(this, property.GetValue(_base, null), null);
}
}
public string HouseProp { get; set; }
}

How to access Property of generic member in generic class [duplicate]

This question already has answers here:
Accessing properties through Generic type parameter
(2 answers)
Closed 6 years ago.
I am newbie in C#. I am trying to create a Generic class. I have three classes and a Main/Generic class.
Three Classes
public class A
{
public string Name { get; set; }
public string Address { get; set; }
public A(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
public class B
{
public string Name { get; set; }
public string Address { get; set; }
public B(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
public class C
{
public string Name { get; set; }
public string Address { get; set; }
public C(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
Generic Class
public class GenericClass<T>
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
}
I have successfully created a Generic class.
class Program
{
static void Main(string[] args)
{
A objA = new A("Mohit", "India");
GenericClass<A> objGenericClass = new GenericClass<A>(objA);
Console.ReadLine();
}
}
Now, if I need to use Class A/B/C property in the Generic class. How can I use it? I know that class reference type decide on the runtime. So, I can't use it in below way.But, Is there any other way?
public class GenericClass<T>
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
public void UseClassPro()
{
Console.WriteLine("Address " + DynamicObject.Address);//Compile time error here.
}
}
The Other Answers are right, but...
I just want to point out: while those other answers promote valid C# code, they make the generic aspect of you implementation superflous. You don't need generics anymore:
Given a base class or interface like
public interface IHasAddress
{
string Address { get; }
}
you don't need a Generic class anymore for what you are trying to achive (from what i can tell by the code you provided):
public class NotSoGenericClass
{
public GenericClass(IHasAddress obj)
{
DynamicObject = obj;
}
public IHasAddress DynamicObject { get; set; }
}
So as you can see, you can easily implement the desired behaviour w/o generics.
For you as a Beginner, i'd recommend the following basic rules when it comes to generics:
When you think you have to use generics, force yourself to consider abstraction via interfaces, abstract classes or base classes first. This often leads to simpler and cleaner solutions.
Same goes with Reflection. When you think you need Reflection, consider generics (Rule 1 is valid at that point to)
But Nothings wrong with Generics, its just more complex and often not needed. Compare the class above with the generic solution:
public class GenericClass<T> where T : IHasAddress // just for the sake of generics
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
}
Looks more complex and doesn't add any benefit, does it? Also note that you need a Interface/baseclass no matter what. Otherwise, you could also use Reflection (not recommended).
To actually answer your question
The precise answer to your question is:
You have to define that you generic parameter has to be assignable to IHasAddress using
public class GenericClass<T> where T : IHasAddress
^^^^^^^^^^^^^^^^^^^^^
This Part
This way, the compiler knows that T inherits or is of type IHasAddress or what ever you define. You can also pass multiple types at this place which adds mor flexibility when it comes to designing your interfaces.
Maybe, there are points to consider in your usecase which are not obvious from the information you provided in the question. In that case, feel free to add some details and i'll be happy to deep dive into those as well.
define interface:
public interface IABC
{
string Name { get; set; }
string Address { get; set; }
}
and in your generic class definition specify this interface:
public class GenericClass<T> where T: IABC
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public IABC DynamicObject { get; set; }
}
All your 3 classes implemet this interface:
public class A : IABC
public class B : IABC
public class C : IABC
After that you could call properties of IABC
A objA = new A("Mohit", "India");
GenericClass<A> objGenericClass = new GenericClass<A>(objA);
var adress = objGenericClass.DynamicObject.Address;
If you have properties in your generic arguments that share type and name, use a base class:
public class Base
{
public string Address { get; set; }
public A(string _address)
{
Address = _address;
}
}
public class A : Base
{
public string Name { get; set; }
public A(string _name, string _address) : base(_address)
{
Name = _name;
}
}
public class B : Base
{
public string Name { get; set; }
public B(string _name, string _address) : base(_address)
{
Name = _name;
}
}
public class C : Base
{
public string Name { get; set; }
public C(string _name, string _address) : base(_address)
{
Name = _name;
}
}
You can then use the base class as a constraint to your generic class:
public class GenericClass<T> where T : Base
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
public void UseClassPro()
{
Console.WriteLine("Address " + DynamicObject.Address);//Compiles now
}
}
If you can not use a base class, use an interface:
public interface IBase
{
string Address { get; set; }
}
public class A : IBase
{
public string Name { get; set; }
public string Address { get; set; }
public A(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
public class B : IBase
{
public string Name { get; set; }
public string Address { get; set; }
public B(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
public class C : IBase
{
public string Name { get; set; }
public string Address { get; set; }
public C(string _name, string _address)
{
Name = _name;
Address = _address;
}
}
public class GenericClass<T> where T : IBase
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
public void UseClassPro()
{
Console.WriteLine("Address " + DynamicObject.Address);//Compiles now
}
}
There is no 'clean' way of getting a property from a generic class without inheritance, either through an interface or a base class, as shown in the other answers.
If you don't want to use inheritance, you can use reflection, although this is far less efficient than using an inherited class.
// the generic class
public class GenericClass<T> where T: IABC
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public IABC DynamicObject { get; set; }
public T GetPropertyValue<T>(string propertyName)
{
var obj = GetType().GetProperty(propertyName).GetValue(this);
return (T)Convert.ChangeType(obj, typeof(T))
}
}
A objA = new A("Mohit", "India");
GenericClass<A> objGenericClass = new GenericClass<A>(objA);
var address = objGenericClass.GetPropertyValue<string>("address");
I stress that this is an alternative to inheritance that will not be very fast, but it might suit your needs.
Add an interface that implements the similar properties like the following :
public interface IInfo
{
public string Name { get; set; }
public string Address { get; set; }
}
public class GenericClass<T> where T : IInfo
{
public GenericClass(T obj)
{
DynamicObject = obj;
}
public T DynamicObject { get; set; }
public void UseClassPro()
{
Console.WriteLine("Address " + DynamicObject.Address);
}
}

How to build a class with "generic" type and instancing it to the derived one?

I have this situation
public class CustomClass
{
public string stringTest { get; set; }
public int numberTest { get; set; }
public (xy) foo { get; set; }
}
Which will be my main class, then:
public class Base
{
public string somePropery { get; set; }
}
public class Derived : Base
{
public string someOtherProperty { get; set;}
}
public class Derived2 : Base
{
public string someHappyProperty { get; set;}
}
I would like to do this:
CustomClass test = new CustomClass()
{
foo = new Derived()
}
test.foo.someOtherProperty = "Wow!";
or
CustomClass test = new CustomClass()
{
foo = new Derived2()
}
test.foo.someHappyProperty = "Wow!";
Obviously I can't set foo's type as Base and I would prefer to avoid the use of the dynamic type, what is the correct way to handle this?
Make CustomClass generic:
public class CustomClass<T>
where T : Base
{
public string stringTest { get; set; }
public int numberTest { get; set; }
public T foo { get; set; }
}
You can now write:
CustomClass<Derived> test = new CustomClass<Derived>()
{
foo = new Derived()
};
test.foo.someOtherProperty = "Wow!";
Obviously I can't set foo's type as Base
Why not?
If you know it's going to be a Derived, set its type to Derived. If you don't, set it to Base. If you later want to check to see if it is a Derived and set Derived-specific members on it, you can use the is keyword:
if (test.foo is Derived)
{
((Derived) test.foo).someOtherProperty = "Wow!";
}

Categories

Resources