I am having a piece of code in which i delegate certain properties of a class to another class if the class exists. Below you see the start time being defined on the TimeProvider if it exists.
public override DateTime StartTime
{
get
{
return (TimeProvider != null) ? TimeProvider.StartTime : base.StartTime;
}
set
{
if (TimeProvider != null)
{
TimeProvider.StartTime = value;
}
else
{
base.StartTime = value;
}
}
}
Now my 'problem' is that i have a lot more properties (like endtime,currentime) i delegate to the TimeProvider if it is not null. So i would like to have code like:
public override DateTime StartTime
{
get
{
return GetTime(()=>StartTime);
}
set
{
SetTime(()=>StartTime)
}
}
Where the ()=>StartTime expression is sometimes 'evaluated' on the TimeProvider and sometimes on the class itself (they share a baseclass). Can something like this be done? Preferably without using reflection.
Cake
public class Foo
{
private string _string1;
public Foo foo { get; set; }
private T GetProperty<T>(Func<Foo,T> getter)
{
return foo == null
? getter(this)
: getter(foo);
}
private void SetProperty(Action<Foo> setter)
{
if (foo == null)
setter(this);
else
setter(foo);
}
public string String1
{
get { return GetProperty(a => a._string1); }
set { SetProperty(a => a._string1 = value); }
}
}
Related
Below are my classes
public class CommonClassSource
{
public int Id {get;set;}
}
public class CommonClassDestination
{
public int Id {get;set;}
}
public class SourceClass
{
public CommonClassSource CommonSource {get;set;}
}
public class DestinationClass
{
public CommonClassDestination CommonDestination {get;set;}
}
Is there any way to add null-checking in config.Bind? For example: here, check if source.CommonSource is null
TinyMapper.Bind<SourceClass, DestinationClass>(config => {
config.Bind(source => source.CommonSource.Id,
target => target.CommonDestination.Id));
});
If all you wanted to have the case handled that it there isn't an issue when source.CommonSource is null, the following script should work for you.
static bool isSourceNull;
public static void Main()
{
Func<SourceClass,object> getSCI = GetSourceClassId;
Func<DestinationClass, object> getDCI = GetDestClassId;
TinyMapper.Bind<SourceClass, DestinationClass>(config => {
config.Bind(source=>getSCI,
target =>getDCI);
});
}
static object GetSourceClassId(SourceClass source)
{
isSourceNull = source.CommonSource == null;
if (isSourceNull) return -1;
else return source.CommonSource.Id;
}
static object GetDestClassId(DestinationClass destinationClass)
{
if (isSourceNull)
{
destinationClass.CommonDestination = null;
return -1;
}
else if (destinationClass.CommonDestination != null)
return destinationClass.CommonDestination.Id;
else return -1;
}
As shown in the first class displayed, I need to cast Activité to Réunion (Réunion extends Activité) but the compiler tells me that I can't. Why? I'll put a scheme so you can better understand my classes structure and also all my other classes. Thank you.
class Employé<T>
{
private string nom;
private Local bureau;
private LinkedList<Activité<T>> activités;
public Employé(string nom, Local bureau)
{
this.nom = nom;
this.bureau = bureau;
}
public void AjouteActivité(params Activité<T>[] activités)
{
foreach(Activité<T> activité in activités)
{
if (activité as Réunion != null)
// here's the problem !!! ((Réunion)activité).EmployéConvoqués = activité;
}
}
}
Here's the scheme of my classes structure:
And here are the other classes:
abstract class Activité<T>
{
private string label;
private DateTime début, fin;
private T lieu;
private readonly int id;
private static int CPT = 0;
public Activité(string label, DateTime début, DateTime fin, T lieu)
{
this.label = label;
this.début = début;
this.fin = fin;
this.lieu = lieu;
this.id = ++CPT;
}
public override string ToString()
{
return $"{id} : {label}(de {début} à {fin}) - {DescriptionLieu()}";
}
public double Duree()
{
return fin.Subtract(début).TotalMinutes;
}
public int Id
{
//tester get; seulement
get
{
return id;
}
}
public T Lieu
{
get
{
return lieu;
}
}
public abstract string DescriptionLieu();
}
class ActivitéExtérieure : Activité<string>
{
public ActivitéExtérieure(string label, DateTime début, DateTime fin, string lieu) : base(label,début,fin,lieu) { }
public override string DescriptionLieu()
{
return Lieu;
}
}
class ActivitéInterne : Activité<Local>
{
public ActivitéInterne(string label, DateTime début, DateTime fin, Local lieu) : base(label,début,fin,lieu)
{
lieu.AjouteActivité(this);
}
public override string DescriptionLieu()
{
return $"local :: {Lieu.NumComplet}";
}
}
class Employé<T>
{
private string nom;
private Local bureau;
private LinkedList<Activité<T>> activités;
public Employé(string nom, Local bureau)
{
this.nom = nom;
this.bureau = bureau;
}
public void AjouteActivité(params Activité<T>[] activités)
{
foreach(Activité<T> activité in activités)
{
if (activité as Réunion != null)
((Réunion)activité).EmployéConvoqués = activité;
}
}
}
class Local
{
private int etage;
private int numero;
private bool possedeWifi;
private Dictionary<int, ActivitéInterne> historiquesActivités;
public int Numero
{
get
{
return numero;
}
set
{
if (value < 0 || value > 99)
throw new IndexOutOfRangeException();
else
numero = value;
}
}
public int NumComplet
{
get
{
return etage * 100 + numero;
}
}
public bool PossedeWifi
{
get
{
return possedeWifi;
}
}
public Local(int etage, bool possedeWifi, int numero)
{
this.etage = etage;
this.possedeWifi = possedeWifi;
Numero = numero;
}
public Local(int etage, int numero) : this(etage, true, numero) { }
public Local(int local, bool possedeWifi) : this(local / 100, possedeWifi, local % 100) { }
public void AjouteActivité(ActivitéInterne a)
{
historiquesActivités.Add(a.Id, a);
}
}
class Réunion : ActivitéInterne
{
private HashSet<Employé<Local>> employésConvoqués;
public Réunion(string label, DateTime début, DateTime fin, Local lieu) : base(label, début, fin, lieu) { }
public Employé<Local> EmployéConvoqués
{
set
{
employésConvoqués.Add(value);
}
}
}
The error message says that "cast is redundant". This is because you have already tested for "activité as Réunion != null". The compiler figures out that in the 'if' clause this condition is already true, therefore the cast is not meaningful. On the other hand you cannot access activité.EmployéConvoqués because the static type of activité is not Réunion.
All you have to do is introduce a new variable when testing the type. Like this:
if (activité is Réunion réunion) {
réunion.EmployéConvoqués = activité;
}
However if you try this you will see that the assignment cannot be done because you are trying to assign an activity to an Employé<Local>. These are not compatible types. Perhaps you meant something like
foreach (Activité<T> activité in activités) {
if (activité is Réunion réunion && this is Employé<Local> employéLocal) {
réunion.EmployéConvoqués = employéLocal;
}
}
Comment: in the definition of Réunion you are adding to HashSet<Employé<Local>> employésConvoqués when setting the property Employé<Local> EmployéConvoqués. From a style point of view this is strange because people generally expect a property of type Employé<Local> will represent a single Employé<Local> rather than a collection of Employé<Local>. I would suggest that you remove the setter and instead define
public void Ajoute( Employé<Local> employéConvoqué) {
this.employésConvoqués.Add(employéConvoqué);
}
I created my own checkbox (UserControl). It has a property called ControlSource which works as the binding source. However, the Data Type of ControlSource is also a custom type. After playing around,
...
[System.ComponentModel.Bindable(true), Browsable(true), Category("Behavior")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public IMyBool ControlSource
{
get { return this.chx.Checked ? IMyBool.True : IMyBool.False; }
set { this.chx.Checked = value.Value; }
}
...
I tried an interface solution here:
public interface IMyBool
{
bool Value { get; set; }
IMyBool True { get; }
IMyBool False { get; }
}
public class MyBool
{
protected bool? _bValue = null;
protected string _sTrue = String.Empty;
protected string _sFalse = String.Empty;
protected string _sNull = String.Empty;
public MyBool(bool? bValue = null)
{
this._bValue = bValue;
}
public override string ToString()
{
return this._bValue.HasValue ? (this._bValue.Value ? _sTrue : _sFalse) : _sNull;
}
public bool Value
{
get { return this._bValue.Value; }
set { this._bValue = value; }
}
}
public class MyInvoiceBool : MyBool, IMyBool
{
public static implicit operator MyInvoiceBool(bool? bValue)
{
return bValue.HasValue ? (bValue.Value ? True : False) : Null;
}
public static implicit operator bool?(MyInvoiceBool ivbValue)
{
return ivbValue._bValue;
}
public MyInvoiceBool(bool? bValue = null)
{
base._sTrue = "Rechnung wird gestellt";
base._sFalse = "Rechnung wird nicht gestellt";
base._bValue = bValue;
}
public static MyInvoiceBool True
{
get { return new MyInvoiceBool(true); }
}
public static MyInvoiceBool False
{
get { return new MyInvoiceBool(false); }
}
public static MyInvoiceBool Null
{
get { return new MyInvoiceBool(); }
}
}
public class MyInvoiceAddressBool : MyBool
{
public static implicit operator MyInvoiceAddressBool(bool? bValue)
{
return bValue.HasValue ? (bValue.Value ? True : False) : Null;
}
public static implicit operator bool?(MyInvoiceAddressBool ivbValue)
{
return ivbValue._bValue;
}
public MyInvoiceAddressBool(bool? bValue = null)
{
base._sTrue = "Abweichende Rechnungsadresse";
base._bValue = bValue;
}
public static MyInvoiceAddressBool True
{
get { return new MyInvoiceAddressBool(true); }
}
public static MyInvoiceAddressBool False
{
get { return new MyInvoiceAddressBool(false); }
}
public static MyInvoiceAddressBool Null
{
get { return new MyInvoiceAddressBool(); }
}
}
My aim is that I can use my own bool data type which knows an alternative string expression for true, false or null. However, the groupbox control should be coded generally. That's why an interface solution came into my mind. However, it does not work. I am pretty sure that there is a "often used" solution, isn't it?
Finally, I chose a work around: I inherited the checkbox and explicitly used my custom data type for the control source property. Thus, I do not need an interface or abstract class... Its not the best solution.
Rather than extending the data type, what about implementing an IValueConverter to generate the string representation?
http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx
Let me explain my question by posing a hypothetical situation. Lets start with a class:
public class PaymentDetails
{
public int Id {get;set;}
public string Status {get;set;}
}
And then I have another class:
public class PaymentHelper
{
private PaymentDetails _paymentDetails;
public PaymentDetails MyPaymentDetails{ get { return _paymentDetails; } }
public PaymentHelper()
{
_paymentDetails = new PaymentDetails();
}
public void ModifyPaymentDetails(string someString)
{
// code to take the arguments and modify this._paymentDetails
}
}
OK, so I have these two classes. PaymentHelper has made the property MyPaymentDetails read-only.
So I cannot instantiate PaymentHelper and modify MyPaymentDetails like this:
PaymentHelper ph = new PaymentHelper();
ph.MyPaymentDetails = new PaymentDetails(); // Not allowed!!!
But I can modify the public properties inside of ph.MyPaymentDetails like this:
ph.MyPaymentDetails.Status = "Some status"; // This is allowed
How do I prevent that from working? Or is there no good way of doing that?
A property may apply access modifiers to individual accessors, for instance:
public string Status { get; private set; }
The scope of access is left to your circumstance. Keeping it private, I'm sure you can tell, will mean only elements within the scope of the current class can use the setter, protected would allow inheritors to use it, etc.
Obviously your classes need to be engineered properly from the bottom up, so as to account for appropriate scoping and robust management when used further up the hierarchy.
The idea of protecting the properties of a complex type that is itself a property isn't available from a language construct at that level.
One option is to design the contained type in such a way as to make its properties read-only using the access modifiers (public set, protected set, private set, etc).
My preference is to expose it as an interface to public consumers:
public class PaymentHelper
{
private PaymentDetails _paymentDetails;
public IPaymentDetails MyPaymentDetails{ get { return _paymentDetails; } }
public PaymentHelper()
{
_paymentDetails = new PaymentDetails();
}
public void ModifyPaymentDetails(string someString)
{
// code to take the arguments and modify this._paymentDetails
}
}
interface IPaymentDetails
{
int Status { get; }
}
Code inside the PaymentHelper class can then use the PaymentDetails class directly, and code outside the class won't be able to use PaymentDetails unless they cast directly to it, which you can stop if you don't release the PaymentDetails class and only provide the interface.
Of course, you can never really stop the determined person who may use reflection to set things. I tend to let these people break the code :-)
Another solution is not to expose the PaymentDetails object directly, but rather wrap the properties you wish to expose. For example:
public class PaymentHelper
{
private PaymentDetails _paymentDetails;
public string PaymentDetailsStatus { get { return _paymentDetails.Status; } }
public PaymentHelper()
{
_paymentDetails = new PaymentDetails();
}
public void ModifyPaymentDetails(string someString)
{
// code to take the arguments and modify this._paymentDetails
}
}
Edit: You could always let the behavior of value types take care of this for you. Change PaymentDetails to a struct instead of a class:
public struct PaymentDetails
{
public int Id { get; set; }
public string Status { get; set; }
}
public class PaymentHelper
{
public PaymentDetails Details { get; set; }
}
If you then try to
ph.Details.Status = "Some status"; //
You'll get a compiler error telling you that you can't do this. Since value types are returned, well, by value, you can't modify the .Status property.
Or...
If PaymentDetails and PaymentHelper are declared in the same class library (separate from the code you want to prevent from writing to the .MyPaymentDetails property, you could use:
public class PaymentDetails
{
public int Id { get; internal set; }
public string Status { get; internal set; }
}
public class PaymentHelper
{
public PaymentDetails Details { get; private set; }
}
which will prevent anything declared outside of that class library from writing to .Id or .Status.
Or, force access to .Id and .Status to go through the helper class instead of allowing read access to a .Details property:
public class PaymentHelper
{
private PaymentDetails _details;
public string Id { get { return _details.Id; } private set { _details.Id=value; } }
public string Status { get { return _details.Status; } private set { _details.Status = value; } }
}
Of course, if you're going to do that, you could just
public calss PaymentDetails
{
public int Id { get; protected set; }
public string Status { get; protected set; }
}
public class PaymentHelper : PaymentDetails
{
}
... assuming that this sort of inheritance fits with the rest of your architecture.
Or, just to illustrate the interface suggestion proposed by #MrDisappointment
public interface IDetails
{
int Id { get; }
string Status { get; }
}
public class PaymentDetails : IDetails
{
public int Id { get; private set; }
public string Status { get; private set; }
}
public class PaymentHelper
{
private PaymentDetails _details;
public IDetails Details { get { return _details; } private set { _details = value; } }
}
So there are two ways that I can think of to deal with this. One is really simple:
public class PaymentDetails
{
private int _id;
private bool _idSet = false;
int Id
{
get
{
return _id;
}
set
{
if (_idSet == false)
{
_id = value;
_idSet == true;
}
else
{
throw new ArgumentException("Cannot change an already set value.");
}
}
}
private string _status;
private bool _statusSet = false;
string Status
{
get
{
return _status;
}
set
{
if (_statusSet == false)
{
_status = value;
_statusSet = true;
}
else
{
throw new ArgumentException("Cannot change an already set value.");
}
}
}
The simple solution only allows values to be set once. Changing anything requires creating a new instance of the class.
The other is rather complex but very versatile:
public interface IPaymentDetails : IEquatable<IPaymentDetails>
{
int Id { get; }
string Status { get; }
}
public class PaymentDetails : IPaymentDetails, IEquatable<IPaymentDetails>
{
public PaymentDetails()
{
}
public PaymentDetails(IPaymentDetails paymentDetails)
{
Id = paymentDetails.Id;
Status = paymentDetails.Status;
}
public static implicit operator PaymentDetails(PaymentDetailsRO paymentDetailsRO)
{
PaymentDetails paymentDetails = new PaymentDetails(paymentDetailsRO);
return paymentDetails;
}
public override int GetHashCode()
{
return Id.GetHashCode() ^ Status.GetHashCode();
}
public bool Equals(IPaymentDetails other)
{
if (other == null)
{
return false;
}
if (this.Id == other.Id && this.Status == other.Status)
{
return true;
}
else
{
return false;
}
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return base.Equals(obj);
}
IPaymentDetails iPaymentDetailsobj = obj as IPaymentDetails;
if (iPaymentDetailsobj == null)
{
return false;
}
else
{
return Equals(iPaymentDetailsobj);
}
}
public static bool operator == (PaymentDetails paymentDetails1, PaymentDetails paymentDetails2)
{
if ((object)paymentDetails1 == null || ((object)paymentDetails2) == null)
{
return Object.Equals(paymentDetails1, paymentDetails2);
}
return paymentDetails1.Equals(paymentDetails2);
}
public static bool operator != (PaymentDetails paymentDetails1, PaymentDetails paymentDetails2)
{
if (paymentDetails1 == null || paymentDetails2 == null)
{
return ! Object.Equals(paymentDetails1, paymentDetails2);
}
return ! (paymentDetails1.Equals(paymentDetails2));
}
public int Id { get; set; }
public string Status { get; set; }
}
public class PaymentDetailsRO : IPaymentDetails, IEquatable<IPaymentDetails>
{
public PaymentDetailsRO()
{
}
public PaymentDetailsRO(IPaymentDetails paymentDetails)
{
Id = paymentDetails.Id;
Status = paymentDetails.Status;
}
public static implicit operator PaymentDetailsRO(PaymentDetails paymentDetails)
{
PaymentDetailsRO paymentDetailsRO = new PaymentDetailsRO(paymentDetails);
return paymentDetailsRO;
}
public override int GetHashCode()
{
return Id.GetHashCode() ^ Status.GetHashCode();
}
public bool Equals(IPaymentDetails other)
{
if (other == null)
{
return false;
}
if (this.Id == other.Id && this.Status == other.Status)
{
return true;
}
else
{
return false;
}
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return base.Equals(obj);
}
IPaymentDetails iPaymentDetailsobj = obj as IPaymentDetails;
if (iPaymentDetailsobj == null)
{
return false;
}
else
{
return Equals(iPaymentDetailsobj);
}
}
public static bool operator == (PaymentDetailsRO paymentDetailsRO1, PaymentDetailsRO paymentDetailsRO2)
{
if ((object)paymentDetailsRO1 == null || ((object)paymentDetailsRO2) == null)
{
return Object.Equals(paymentDetailsRO1, paymentDetailsRO2);
}
return paymentDetailsRO1.Equals(paymentDetailsRO2);
}
public static bool operator != (PaymentDetailsRO paymentDetailsRO1, PaymentDetailsRO paymentDetailsRO2)
{
if (paymentDetailsRO1 == null || paymentDetailsRO2 == null)
{
return ! Object.Equals(paymentDetailsRO1, paymentDetailsRO2);
}
return ! (paymentDetailsRO1.Equals(paymentDetailsRO2));
}
public int Id { get; private set; }
public string Status { get; private set;}
}
public class PaymentHelper
{
private PaymentDetails _paymentDetails;
public PaymentDetailsRO MyPaymentDetails
{
get
{
return _paymentDetails;
}
}
public PaymentHelper()
{
_paymentDetails = new PaymentDetails();
}
public void ModifyPaymentDetails(string someString)
{
// code to take the arguments and modify this._paymentDetails
}
}
The complex solution allows a changeable backing store, but presents a readonly version to the consumer that cannot be changed by outsiders to your helper class.
Note that both patterns only work if you implement them all the way down the object graph or stick to value types and strings.
You can't prevent that, the property returns a refrence to a PaymentDetails, and once somebody has that, it is out of your control.
However, you can just wrap the PaymentDetails. Instead of returning it verbatim, offer only getters for its public properties.
You can also assign access modifiers for the PaymentDetails class like so:
public string Status { get; private set; }
if you don't need the class elsewhere with a public setter.
Yet another solution: Make setters internal
This is the pragmatical way if the PaymentHelper is in the same assembly of PaymentDetails and the clients of PaymentHelper are in another assembly.
Yet another solution: Delegate from PaymentHelper to PaymentDetails.
This is to add the same properties to PaymentHelper as in PaymentDetails.
If you have many properties you can let generate the delegating properties into PaymentHelper by ReSharper. Place cursor on *_paymentDetails* of line
private PaymentDetails _paymentDetails;
Press Alt+Insert->Delegating Members. Then all PaymentHelper properties delegate to PaymentDetails properties.
I have a class Client like that:
public class Client
{
public Person Pers { get; set; }
}
And I have 2 Person´s child class :
public class PersonType1 : Person {...}
public class PersonType2 : Person {...}
So, my Client could be PersonType1 or PersonType2...
I load 2 Client using NHibernate... And after that, I´m trying to compare than (the difference are on PersonType1 and PersonType2 attributes)...
I tried that:
public class ClientComparer : IComparer<Client>
{
public int Compare(Client __c1, Client __c2)
{
string _name1 = __c1.Person.GetType().Equals(typeof(PersonType2)) ? ((PersonType2)(__c1.Person)).Type2Att : ((PersonType1)(__c1.Person)).Type1Att ;
string _name2 = __c2.Person.GetType().Equals(typeof(PersonType2)) ? ((PersonType2)(__c2.Person)).Type2Att : ((PersonType1)(__c2.Person)).Type1Att;
if (_name1 == null)
{
if (_name2 == null)
{
return 0;
}
return -1;
}
if (_name2 == null)
{
return 1;
}
return _name1.CompareTo(_name2);
}
}
The problem is that __c1.Person.GetType() returs PersonProxy127b2a2f44f446089b336892a673643b instead of the correct type... It´s because of NHibernate...
How can I do that ? Ideas?
Thanks
Rather than having two different attributes on PersonType1 and PersonType2, define a single property in the base class Person and override it in each of the child classes. Using polymorphic behavior rather than explicit type-checking is better in any case, and essential when you're using NHibernate's proxied classes. Something like this might accomplish what you want:
public class Person
{
public string Name {get;}
}
public class PersonType2 : Person
{
private string something;
public override string Name
{
get
{
return something;
}
set
{
something = value;
}
}
}
public class PersonType2 : Person
{
private string somethingElse;
public override string Name
{
get
{
return somethingElse;
}
set
{
somethingElse = value;
}
}
}
public class Client
{
public int Compare(Client __c1, Client __c2)
{
return __c1.Pers.Name.CompareTo(__c2.Pers.Name);
}
}
Use the is operator instead of GetType():
public class ClientComparer : IComparer<Client>
{
public int Compare(Client __c1, Client __c2)
{
string _name1 = GetName(__c1.Person);
string _name2 = GetName(__c2.Person);
if (_name1 == null)
{
if (_name2 == null)
{
return 0;
}
return -1;
}
if (_name2 == null)
{
return 1;
}
return _name1.CompareTo(_name2);
}
private string GetName(Person person)
{
if (person is Person1)
{
return ((Person1)person).Type1Att;
}
else if (person is Person2)
{
return ((Person2)person).Type2Att;
}
else
{
throw new ArgumentException("Unhandled Person type.");
}
}
}