I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}
Related
I am not sure that this title is correct..Anyways I have a class that has a number of methods that control a stereo. Each method will send a command to a serial port. There are many models of stereos supported and each stereo may have a different command that needs to be sent.
For example model_A may need to send the command "VOLUP" to the serial port and "model_B" may need to send the command "GAINUP" to increase the volume. I want to have one method called IncreaseVolume like this:
public void IncreaseVolume()
{
serialPort.WriteLine(volumeCommand);
}
This method will be called from another class after setting the model of the radio. Now for two radios I could do this:
public class StereoControl
{
string volumeCommand;
string model_A_Volume_Command = "VOLUP";
string model_B_VOlume_Command = "GAINUP";
public void Set_Radio_Model(string model)
{
if (model == "modelA")
{
volumeCommand = model_A_Volume_Command;
}
else if (model == "modelB")
{
volumeCommand = model_B_Volume_Command;
}
}
public void IncreaseVolume(volumeCommand)
{
serialPort.WriteLine(volumeCommand);
}
}
So the main program will first set the model and then anytime the volume needs increasing it will just call the IncreaseVolume method.
The things is that there are potentially dozens of stereos and dozens of commands and I don't necessarily want all these in if then or case statements.
I thought of creating structures for each model containing the commands but then how do you select which structure to use in the methods?
I am sure there is a more elegant way to do this and am open to suggestions.
The first answer while usable, when we get 100+ commands and 200+ stereo's it will be a bit too difficult to handle. So here is another possibility but I do not know how to get the class reference available throughout the application.
public Class Model_A
{
string volumeCommand = "VOLUP";
}
public Class Model_B
{
string volumeCommand = "GAINUP";
}
public Class StereoControl
{
public void Set_Radio_Model(String model)
{
if (model == "model_a")
{
var _radio = new Model_A();
}
else if (model == "model_b")
{
var _radio = new Model_B();
}
}
public void IncreaseVolume()
{
serialPort.WriteLine(_radio.volumeCommand);
}
}
Of course the issue here is that the scope of _radio is only within the Set_Radio_Model. Is there a way to _radio usable everywhere?
Tom
The very basic way is to have Enum of stereos names and then implement it in OOP
(I hope people help to improve it) this is just depends on my opinion.
1- Define enum like:
public enum StereoBrand
{
Stero1 = 0,
Stereo2 = 1
}
2- Define an interface to enforce all stereos implement IncreaseVolume() like:
public interface IStereo
{
string VolumeCommand { get; }
string SteroeName { get; }
void IncreaseVolume();
}
by above interface each stereo should have a name as StereoName.
3- And then implement StereoController like :
public class SteroController : IStereo
{
public virtual string SteroeName
{
get
{
return string.Empty;
}
}
public virtual string VolumeCommand
{
get
{
return string.Empty;
}
}
public virtual void IncreaseVolume()
{
throw new NotImplementedException();
}
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
switch (brand)
{
case StereoBrand.Stero1:
stereo = new Stereo1();
break;
case StereoBrand.Stereo2:
stereo = new Stereo2();
break;
}
return stereo;
}
}
Notes of Step3:
3.1- StereoController implement IStereo and change that prop and Increase method to Virtual that all Stereo can override them.
3.2- GenerateStereo which create related stereo by its StereoName
4- Suppose we have to implement Stereo classes here Stereo1 and Stereo2 like:
public class Stereo1 : SteroController
{
public override string SteroeName
{
get
{
return "Streo1";
}
}
public override string VolumeCommand
{
get
{
return "Command1";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand
}
public Stereo1()
{
}
}
public class Stereo2 : SteroController
{
public override string SteroeName
{
get
{
return "Streo2";
}
}
public override string VolumeCommand
{
get
{
return "Command2";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand2
}
public Stereo2()
{
}
}
5- The last step is using them like:
var stero = SteroController.GenerateStereo((StereoBrand)Enum.Parse(typeof(StereoBrand), "brandName"));
stero.IncreaseVolume();
Notes:
N1: This is better to implement GenerateStereo by reflection which means find all IStereo and make an instance by reflection.
N2: The another solution to avoid switch-case is using reflection to find related Stereo like:
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
var type = typeof(IStereo);
var types = AppDomain.CurrentDomain.GetAssemblies()//Find all classes which implemented ISereo
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p)).ToList();
foreach(Type t in types)
{
var stereoNameProp = t.GetProperties().SingleOrDefault(p => p.Name == "StereoName");//Get stereo name prop
if (stereoNameProp != null && stereoNameProp.GetValue(t).ToString() == brand.ToString())//Check it with brand name
stereo =(SteroController)Activator.CreateInstance(type);//Make an instance
}
return stereo;
}
Hope it help and give you the clue.
There is tons of info about skipping Properties based on conditionals, but I would like to skip the entire object based on conditions within the object's class. I would like a solution that is contained within the object's class if at all possible. Keep in mind this is a collection of myObj that I am serializing.
public class myObj
{
bool conditional;
ShouldSerialize()
{
return conditional;
}
}
Or
public class myObj
{
[JsonCondition]
public bool conditional{get;}
}
Or even
[JsonCondition(typeof(MyConditionChecker))]
public class myObj
{
public bool conditional{get;}
}
class MyConditionChecker: JsonCondition
{
public override bool CanConvert(object sourceObj)
{
return (sourceObj as myObj).conditional;
}
}
What I got from your comments you would be best served creating your own wrapper around Json that applies the filtering.
public interface IConditionalSerializer
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional<T>(IEnumerable<T> input)
where T : IConiditionalSerializer
{
return JsonConvert.SerializeObject(input.Where(e => e.ShouldBeSerialized()));
}
}
public class Demo : IConditionalSerializer
{
public bool ShouldBeSerialized() => false;
}
You might also replace the interface with a reflection approach, but keep in mind the performance loss.
public interface IConiditionChecker
{
bool ShouldBeSerialized(object instance);
}
public class ConditionAttribute : Attribute
{
public Type ConditionChecker { get; set; }
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let att = entry.GetType().GetCustomAttribute<ConditionAttribute>()
let hasChecker = att != null && att.ConditionChecker != null
let checker = hasChecker ? (IConiditionChecker)Activator.CreateInstance(att.ConditionChecker) : null
where checker.ShouldBeSerialized(entry)
select entry);
return JsonConvert.SerializeObject(matches);
}
}
[Condition(ConditionChecker = typeof(SomeChecker))]
public class Demo
{
}
Edit: Based on your comment you could do this. Only must decide wether to use opt-in or opt-out in the where-statement. It must ether be casted != null && casted.ShouldBeSerialized or what it currently says.
public interface IShouldBeSerialized
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let casted = entry as IShouldBeSerialized
where casted == null || casted.ShouldBeSerialized()
select entry);
return JsonConvert.SerializeObject(matches);
}
}
public class Demo : IShouldBeSerialized
{
public bool ShouldBeSerialized()
{
return false;
}
}
If you're able to use the JSON.NET serializer, in terms of not serializing specific items within a collection, you could make the main collection non serializable, then add another filtered collection that does serialize.
public class Manager
{
[JsonIgnore]
public Employee[] Employees { get; set; }
[JsonProperty("Employees")]
public Employee[] SerializableEmployees
{
get { return Employees.Where(e => e.Name != "Bob").ToArray(); }
set { Employees = value; }
}
}
Alternatively, you could mark your class with the [JsonConverter] attribute and use a custom converter to check your condition. A similar approach that ignores a class entirely is detailed here.
Let's say I have a class called Customer with some properties:
public class Customer
{
public string CustAddr = GetCustAddr(); //Long procedure returning address
public double CustAcct = GetCustAcct(); //Long procedure returning account
public string CustInvoice = GetCustInvoice(); //Long procedure returning invoice
}
This class is returned via a function:
public Customer GetData(string query)
{
Customer cust = new Customer();
//set the values for each of the properties
return cust;
}
Right now it is returning the whole class and I can use it like this:
lblDisplay = GetData("QUERY").CustAddr.ToString();
However, suppose each property takes a lot of time to compute. If I only want the CustAddr value, it still computes and has CustAcct and CustInvoice available for me.
How do I alter my function to only return the property I'm looking for, aside from breaking up my class into individual procedures to call? For example, I could just:
lblDisplay = GetCustAddr().ToString();
but that's not what I'm looking for. I think it's better to have all my data in an organized structure instead of a bunch of different procedures.
This is a great candidate for lazy initialization. Here I present an example using properties (you have fields).
public class Customer
{
public Lazy<string> CustAddr { get; private set; }
public Lazy<double> CustAcct { get; private set; }
public Lazy<string> CustInvoice { get; private set; }
public Customer()
{
CustAddr = new Lazy<string>(GetCustAddr);
CustAcct = new Lazy<double>(GetCustAcct);
CustInvoice = new Lazy<string>(GetCustInvoice);
}
}
However, I would be remiss if I didn't point out that you should not use floating-point types (float, double) to store monetary values. Consider instead using decimal.
Why use an exotic solution when there's a vanilla one?
Implementing the calculation on the get of the properties.
NB: What you have are public fields, not properties
Very simple solution (nothing exotic!)
See this fiddle
e.g.
public class Customer
{
private double ? _custAcct = null;
public double CustAcct
{
get
{
if (!_custAcct.HasValue)
{
_custAcct = GetCustAcct();
}
return _custAcct.Value;
}
}
private double GetCustAcct()
{
// do something that takes a long time
return 1234.45;
}
}
What you're talking about is lazy loading or lazy initialization. You write your properties something like this:
public class MyLazyWidget
{
. . .
public BigExpensiveObject MyLazyProperty
{
get
{
if ( BigExpensiveObjectBackingStore == null )
{
BigExpensiveObjectBackingStore = ExpensiveOperation() ;
}
return BigExpensiveObjectBackingStore ;
}
}
private static BigExpensiveObjectBackingStore = null ;
. . .
}
And if your app is multi-threaded, you'll need to worry about race conditions, so you need to synchronize access to the static backing store:
public class MyLazyWidget
{
. . .
public BigExpensiveObject MyLazyProperty
{
get
{
lock( MyLazyPropertyLatch )
{
if ( BigExpensiveObjectBackingStore == null )
{
BigExpensiveObjectBackingStore = ExpensiveOperation() ;
}
}
return BigExpensiveObjectBackingStore ;
}
}
private static readonly object MyLazyPropertyLatch = new object() ;
private static BigExpensiveObjectBackingStore = null ;
. . .
}
I have two interfaces and the both have the same exact properties.
Just in case you're wondering why I've got two interfaces like these it's a long story, but yes, it has to be this way.
Based on a condition a List is returned if condition is the other way a List will be returned.
By looking at my interfaces and my code below I need to be able to make use of one object, in other words if doesn't matter which interface is returned I need to be able to work with one object and not looping one List interface and setting properties of the other.
I need something like this
compParts = genCompParts;
--- Code usage
public class ComponentParts : IComponentParts
{
public ComponentParts() { }
public ComponentParts(Guid userID, int compID, bool isGeneric)
{
List<IComponentPart> compParts = null;
List<IComponentPart_Max> genCompParts = null;
if (isGeneric)
{
genCompParts = GenericCatalogBL.GenericCatalogManagerBL.GetComponentPartsMax(compID);
}
else
{
compParts = CatalogManagerDL.GetComponentParts(userID, compID);
}
var verParts = compParts.Where(x => x.CompTypeName.ToLower().Contains("vertical"));
if (verParts.Count() > 0) { this.Vertical = verParts.ToList<IComponentPart>(); }
var horParts = compParts.Where(x => x.CompTypeName.ToLower().Contains("horizontal"));
if (horParts.Count() > 0) { this.Horizontal = horParts.ToList<IComponentPart>(); }
//... redundant code omitted
---Interface Snapshots---
I ended up creating a class library call Interfaces and I just share those interfaces across different programs in my solution.
It's what I should of done in the first place, just being lazy.
The totally brute-force way, assuming you don't own either IComponentPart or IComponentPart_Max and can't fix one of them.
Make a new interface that you control
interface IComponentPart {
string BrandGroup {get; set;}
int BrandID {get; set;}
// ...
}
Make wrappers for both of the existing interfaces that adapt them to your interface
class IComponentPartWrapper : IComponentPart {
private readonly CatelogDL.IComponentPart _underlyingPart;
public IComponentPartWrapper(CatelogDL.IComponentPart underlyingPart) {
_underlyingPart = underlyingPart
}
public string BrandGroup {
get {return _underlyingPart.BrandGroup;}
set {_underlyingPart.BrandGroup = value;}
}
public int BrandID {
get {return _underlyingPart.BrandID ;}
set {_underlyingPart.BrandID = value;}
}
// ...
}
class IComponentPart_MaxWrapper : IComponentPart {
private readonly GenericCatalogDL.IComponentPart_Max _underlyingPart;
public IComponentPartWrapper(GenericCatalogDL.IComponentPart_Max underlyingPart) {
_underlyingPart = underlyingPart
}
public string BrandGroup {
get {return _underlyingPart.BrandGroup;}
set {_underlyingPart.BrandGroup = value;}
}
public int BrandID {
get {return _underlyingPart.BrandID ;}
set {_underlyingPart.BrandID = value;}
}
// ...
}
Make your code use your interface, and wrap the results from either library in the corresponding wrapper
public class ComponentParts : IComponentParts
{
public ComponentParts() { }
public ComponentParts(Guid userID, int compID, bool isGeneric)
{
List<IComponentPart> compParts;
if (isGeneric)
{
compParts = GenericCatalogBL.GenericCatalogManagerBL.GetComponentPartsMax(compID)
.Select(x => new IComponentPart_MaxWrapper(x))
.ToList();
}
else
{
compParts = CatalogManagerDL.GetComponentParts(userID, compID)
.Select(x => new IComponentPartWrapper(x))
.ToList();
}
// ...
Assuming there's an enumeration defined as follows:
public enum Beep
{
HeyHo,
LetsGo
}
I wonder if it's possible to improve the following property:
public Dictionary<Beep, String> Stuff{ get; set; }
...
String content = Stuff[Beep.HeyHo]
because the way it's right now, I retrieve the dictionary and then pick out the element I need. I wonder if it's (a) possible at all and if so (b) recommended to create something like this pseudo-code.
public String Stuff{ get<Beep>; set<Beep>; }
...
String content = Stuff[Beep.HeyHo]
You can apply an indexer to your class.
It is recommended, as it improves encapsulation. For example, it's perfectly possible using the original code to replace the Dictionary entirely with a different dictionary - which is probable not desirable.
public class MyClass
{
// Note that dictionary is now private.
private Dictionary<Beep, String> Stuff { get; set; }
public String this[Beep beep]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal dictionary.
return this.Stuff[beep];
}
set
{
this.Stuff[beep] = value;
}
}
// Note that you might want Add and Remove methods as well - depends on
// how you want to use the class. Will client-code add and remove elements,
// or will they be, e.g., pulled from a database?
}
Usage:
MyClass myClass = new MyClass();
string myValue = myClass[Beep.LetsGo];
You can also use an indexer.
class MyClass
{
private readonly Dictionary<Beep, string> _stuff = new Dictionary<Beep, string>();
public string this[Beep beep]
{
get { return _stuff[beep]; }
set { _stuff[beep] = value; }
}
}
Now, instead of calling
var obj = new MyClass();
string result = obj.Stuff[Beep.HeyHo];
You can call
var obj = new MyClass();
string result = obj[Beep.HeyHo];
Indexers work much like properties but have at least one argument used as index. You can have only one indexer per class, however you can create different overloads of it. The same overloading rules apply as for methods.
Something like this using Indexer
public class Stuff
{
public Dictionary<Beep, String> _stuff { get; set; }
public enum Beep
{
HeyHo,
LetsGo
}
public Stuff()
{
_stuff = new Dictionary<Beep, string>();
// add item
_stuff[Beep.HeyHo] = "response 1";
_stuff[Beep.LetsGo] = "response 2";
}
public string this[Beep beep]
{
get { return _stuff[beep]; }
}
}
Sample Usage :
public static class Program
{
private static void Main()
{
Stuff stuff = new Stuff();
string response;
response = stuff[Stuff.Beep.HeyHo]; // response 1
response = stuff[Stuff.Beep.LetsGo]; // response 2
}
}