Winforms DataGridView columns from datasource - c#

I have base class and some inherited classes, like this:
public abstract class Base
{
public long ID { get; set; }
public string Name { get; set; }
public virtual string Description { get { return "Base"; } }
}
public class A : Base
{
public override string Description { get { return "A"; } }
}
public class B : Base
{
private string extraInfo;
public override string Description { get { return "B"; } }
public string ExtraInfo
{
get { return extraInfo; }
set { extraInfo = value; }
}
}
I have collection of these objects and I set this collection to DataSource of DataGridView. Then, columns of DataGridView will be created by Base class's properties (ID, Name. Description). Is there any way to reflect also concrete implementation properties?
List<Base> items = new List<Base>();
DataGridView dgv = new DataGridView();
dgv.DataSource = new BindingList<Base>(items);
In this case, I want also column for ExtraInfo property of class B.

Inherit class B too:
public class Base
{
public long ID { get; set; }
public string Name { get; set; }
public virtual string Description { get { return "Base"; } }
}
public class A : Base
{
public override string Description { get { return "A"; } }
}
public class B : Base
{
private string extraInfo;
public override string Description { get { return "B"; } }
public string ExtraInfo
{
get { return extraInfo; }
set { extraInfo = value; }
}
}

Related

How to have access to an inherited method in C#?

Am I missing any concept about inheritance? I am trying to call a method that is in a child class but it doesn't work.
This is what I have, so simple:
Vuelo.cs
public class Vuelo
{
private Aeronave _aeronave { get; set; }
public Vuelo(string numero, Aeronave aeronave)
{
ValidarNumero(numero); // validates numero
_aeronave = aeronave;
}
public string modelo_aeronave()
{
return _aeronave.model(); // This is where the error goes, .model()
}
public string RegistroAvion()
{
return _aeronave.Registration(); // This worked perfectly
}
}
Aeronave.cs
public class Aeronave
{
private string _registration { get; set; }
public Aeronave(string registration)
{
_registration = registration;
}
public string Registration()
{
return _registration;
}
}
Airbus319.cs (the child class):
public class AirbusA319 : Aeronave
{
private string _model { get; set; }
public AirbusA319(string model, string registro) : base(registro)
{
_model = model;
}
public string model()
{
return _model;
}
}
I want to show up the model of the Airbus that is in model() like this:
Vuelo vuelo = new Vuelo("AB345", new AirbusA319("G-EUPT", "GG235"));
Console.WriteLine(vuelo.modelo_aeronave());
I can't find solutions in the internet, even in microsoft docs about inheritance.
You would need to modify your classes as shown below. Aeronave should contain model (virtual or abstract) to be overridden in Airbus.
public abstract class Aeronave
{
private string _registration { get; set; }
public Aeronave(string registration)
{
_registration = registration;
}
public string Registration()
{
return _registration;
}
public abstract string model();
}
public class AirbusA319 : Aeronave
{
private string _model { get; set; }
public AirbusA319(string model, string registro) : base(registro)
{
_model = model;
}
public override string model()
{
return _model;
}
}

How to access to common properties of a series of classes without reflection

I am working on a legacy C# application that includes many business entity classes with a 5 common properties same name same type (string and integer).
I need to implement some business process logic on the entity classes based on the 5 common properties.
class A
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class B
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class C
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
// there more of such business classes
public static BusinessHelpr
{
public static DoSomethingOnClassAorBorC(object theRefrence)
{
theRefrence.CommonProperty4 = "result of some complex calculation";
theRefrence.CommonProperty2 = 56; // result of some complex calculation;
theRefrence.CommonProperty5 = "result of some complex calculation";
}
}
If this was a greenfield application, I would inherit from a base class, that includes the 5 properties, and nicely implement the required logic
However, there is a decision that we do not do any refactoring or changing the business entities. They cannot be touched.
As such, In my helper class I need to find a way to get a reference to an object type, and access to its properties by the name of them in a string.
An obvious option here is reflection. That means I get a type, use reflection to access its properties by name in a string.
However, I learned that the use of reflection in this scenario imposes performance penalty and it is not a good practice.
Please note that I simplified the actual scenario to focus on the main point. So creating a method below won't work:
static DoSomethingOnClassAorBorC(string CommonProperty1, int CommonProperty2, string CommonProperty3,string CommonProperty4, string CommonProperty5)
What are my other options, other than reflection?
Option 1
I realize you said you didn't want to make any changes to the model, but one option you didn't cover is to use an interface.
interface ICommon
{
string CommonProperty1 {get;set;}
int CommonProperty2 {get;set;}
string CommonProperty3 {get;set;}
string CommonProperty4 {get;set;}
string CommonProperty5 {get;set;}
}
class A : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class B : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class C : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
Then you can just use:
static DoSomethingOnClassAorBorC(ICommon common)
{
// implementation
}
and any of your entities will "just work".
You literally wouldn't have to make any changes to the entities except adding : Interface to each one, which is less invasive than using inheritance.
Option 2
If you really don't want to make any changes to your models and don't want to incur a huge performance hit (both Reflection and dynamic are expensive), the only other option is to use an adapter pattern on each of your models.
interface ICommon
{
string CommonProperty1 {get;set;}
int CommonProperty2 {get;set;}
string CommonProperty3 {get;set;}
string CommonProperty4 {get;set;}
string CommonProperty5 {get;set;}
}
Create an adapter class for each of your entities.
class AAdapter : ICommon
{
private readonly A inner;
public AAdapter(A inner)
{
if (inner == null)
throw new ArgumentNullException(nameof(inner));
this.inner = inner;
}
public string CommonProperty1
{
get { return inner.CommonProperty1; }
set { inner.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return inner.CommonProperty2; }
set { inner.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return inner.CommonProperty3; }
set { inner.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return inner.CommonProperty4; }
set { inner.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return inner.CommonProperty5; }
set { inner.CommonProperty5 = value; }
}
}
class BAdapter : ICommon
{
private readonly B inner;
public BAdapter(B inner)
{
if (inner == null)
throw new ArgumentNullException(nameof(inner));
this.inner = inner;
}
public string CommonProperty1
{
get { return inner.CommonProperty1; }
set { inner.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return inner.CommonProperty2; }
set { inner.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return inner.CommonProperty3; }
set { inner.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return inner.CommonProperty4; }
set { inner.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return inner.CommonProperty5; }
set { inner.CommonProperty5 = value; }
}
}
// Other similar adapters...
Declare the method the same way as Option 1:
static DoSomethingOnClassAorBorC(ICommon common)
{
// implementation
}
And wrap your entity classes to use them.
DoSomethingOnClassAorBorC(new AAdapter(a));
DoSomethingOnClassAorBorC(new BAdapter(b));
DoSomethingOnClassAorBorC(new CAdapter(c));
The best way I can think of here is to simply wrap A, B, and C in another class that implements an interface, like ICommon:
public interface ICommon
{
string CommonProperty1 { get; set; }
int CommonProperty2 { get; set; }
string CommonProperty3 { get; set; }
string CommonProperty4 { get; set; }
string CommonProperty5 { get; set; }
}
public class A2 : ICommon
{
private readonly A _data;
public A2(A data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
public class B2 : ICommon
{
private readonly B _data;
public B2(B data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
public class C2 : ICommon
{
private readonly C _data;
public C2(C data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
var list = new List<ICommon> { new A2(new A()), new A2(new A()), new B2(new B()), new C2(new C()) };
foreach (var item in list)
{
item.CommonProperty1 = "a";
item.CommonProperty2 = 2;
item.CommonProperty3 = "b";
item.CommonProperty4 = "c";
item.CommonProperty5 = "d";
}

How to serialize to XML generic classes?

I have these interfaces:
public interface IParameter
{
string Name { get; }
object UntypedValue { get; set; }
}
public interface IValidationPolicy<T>
{
bool Validate(T toValidate);
T Default();
}
A parameter base class
[Serializable]
public abstract class ParameterBase : IParameter
{
public abstract string Name { get; protected set; }
public abstract object UntypedValue { get; set; }
}
A parameter concrete class (I have more but them are quite similar):
public class Parameter<T, V> : ParameterBase where V : IValidationPolicy<T>
{
[XmlAttribute("Name")]
public override string Name { get; protected set; }
[XmlIgnore]
protected V validation_policy_;
[XmlElement("AnyValidation", Type = typeof(AnyValidation<>))]
[XmlElement("MultiOptionsValidation", Type = typeof(MultiOptionsValidation<>))]
[XmlElement("RangeValidation", Type = typeof(RangeValidation<>))]
[XmlElement("TextValidation", Type = typeof(TextValidation))]
public V Validation
{
get
{
return validation_policy_;
}
}
[XmlIgnore]
protected T value_;
[XmlElement("Value")]
public T Value
{
get
{
return value_;
}
set
{
if (validation_policy_.Validate(value))
{
value_ = value;
}
}
}
[XmlIgnore]
public object UntypedValue
{
get
{
return Value;
}
set
{
throw new NotImplementedException();
}
}
}
And an XMLParameter class:
public class XMLParameter : INotifyPropertyChanged
{
public string Description { get; set; }
public int PasswordLevel { get; set; }
public bool Enabled { get; set; }
public ParameterBase Parameter { get; set; }
}
How can I serialize and deserialize a list of XMLParameters?
In particular I have problem on serializing the IParameter objects.
Since the interface is not serializable as first attempt I created a base abstract class ParameterBase and derive the Parameter from it.
But when I try to serialize it in a test method:
var validation = new RangeValidation<int>() { MinValue = 1, MaxValue = 6 };
var parameter = new Parameter<int, RangeValidation<int>>();
parameter.Initialize("NumberOfTrays", validation);
parameter.Value = 6;
XElement par = validation.ToXElement<Parameter<int, RangeValidation<int>>>();
I got an exception: Error at reflection of type 'ConfigurableLibray.Parameter'2[System.Int32,ConfigurableLibray.RangeValidation'1[System.Int32]]'
The inner exception says that ConfigurableLibray.Parameter'2[T,V] is not supported
What am I doing wrong?
Thanks in advance for any suggestion!
I solved implementing manually the serialization and deserialization of the classes using reflection.

How to achieve Multiple inheritance in C#?

I have the below code in my Application.
public class GeneralInfo
{
private string _id;
private string _name;
public string id
{
set
{
_id = value;
}
get
{
return _id;
}
}
public string name
{
set
{
_name = value;
}
get
{
return _name;
}
}
}
public class SecureInfo
{
private string _password;
public string password
{
set
{
_password = value;
}
get
{
return _password;
}
}
}
public class User
{
}
I need to apply multiple inheritance in the above code ie. the classes GeneralInfo,SecureInfo properties should be accessible in the user class.
I know using interface Multiple inheritance can be achieved. But i need to define the properties in the base class which is restricted in Interface.
How I can achieve this?
C# does not support multiple inheritance. However you can achieve this via multiple interfaces.
public interface ISecureInfo
{
}
public interface IGeneralInfo
{
}
public class UserClass : ISecureInfo, IGeneralInfo {
}
You probably better off encapsulating the data in the class rather than trying to use something to do multiple inheritance here. See this question for some arguments for this.
You can achieve this through interface based inheritance:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
// Implementation of IGeneralInfo
public String Id { get; set; }
public String Name { get; set; }
// Implementation of ISecureInfo
public String Password { get; set; }
}
Or, going one step further, through composition:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public class GeneralInfo : IGeneralInfo
{
public String Id { get; set; }
public String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class SecureInfo : IGeneralInfo
{
public String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
private GeneralInfo generalInfo = new GeneralInfo();
private SecureInfo secureInfo = new SecureInfo();
public String Id {
get { return generalInfo.Id; }
set { generalInfo.Id = value; }
}
public String Name {
get { return generalInfo.Name; }
set { generalInfo.Name = value; }
}
public String Password {
get { return secureInfo.Password; }
set { secureInfo.Password = value; }
}
}
From your sample description, encapsulation might be what you might want to use:
public class Info{
GeneralInfo general;
SecureInfo secure;
...
}
You cannot do multiple inheritance in C# because it is not supported like C++. In C# you can use interfaces for it and implement method and properties. For sample, you could have a base class
public abstract class Entity
{
public string Name { get; set; }
}
You also could have some interfaces:
public interface IPrint
{
void Print();
}
public interface IGenerate
{
void Generate();
}
And use it like multiples inheritance (but it is not, it is just a single inheritance and interfaces)
public class User : Entity, IPrint, IGenerate
{
public void Print()
{
// some code
// here you could access Name property, because it is on base class Entity
}
public void Generate()
{
// some code
}
}
And you could instance it using the abstractions:
Entity e = new User();
IPrint p = new User();
IGenerate g = new User();
User u = new User();
If you need implementations, you could do a hiearachy inherits, for sample:
User inherit from Person that inherit from Entity.
public class Entity
{
public int Id { get; set; }
public void Method()
{
// some code
}
}
public class Person : Entity
{
public string Name { get; set; }
public void AnotherMethod()
{
// some code
}
}
public class User : Person
{
public string Password { get; set; }
public bool CheckUser(string name, string passworkd)
{
// some code
}
}
I think the best would be to seperate the implementation of the interfaces and the real class you have at the end.
What I mean is something like the Bridge Pattern.
Your class (that will implement several interfaces) will just deleagte the method calls to the real implementation, that you can have in a seperate place and only once.
You could also use an approach like this. You would get to the same point than if you would be using multiple inheritance. That way, you could inherit only Entity if you don't need the SecureInfo stuff (i.e. for books and other stuff). Still, I think composition would do better in this case as others say...
class User : SecuredEntity { }
abstract class SecuredEntity : Entity, ISecureInfo
{
public string Password { get; set; }
}
abstract class Entity : IGeneralInfo
{
public string ID { get; set; }
public string Name { get; set; }
}
interface IGeneralInfo
{
string ID { get; set; }
string Name { get; set; }
}
interface ISecureInfo
{
string Password { get; set; }
}

How can I update a property showing text length when my class is updated?

I have the following class. Note there are some key values which are not shown:
namespace Storage.Models
{
public abstract class AuditableTable
{
public string Title { get; set; }
public string Text { get; set; }
}
}
I would like to store the length of the Text property in a variable called TextLength. Is it possible for me to do this automatically when an instance of the class is created or when the class is updated?
You can just add a property with a getter:
public abstract class AuditableTable
{
public string Title { get; set; }
public string Text { get; set; }
public int TextLength
{
get { return this.Text.Length; }
}
}
You don't necessarily need a property, unless you want to record the initial value:
public int TextLength
{
get
{
return this.Text.Length;
}
}
However, if you do want to record the initial length, you can do:
string m_Text;
public string Text
{
get
{
return m_Text;
}
set
{
m_Text = value;
if (m_TextLength == 0)
{
m_TextLength = value.Length;
}
}
}
private int m_TextLength;
public int TextLength
{
get
{
return m_TextLength;
}
}

Categories