I have 2 classes that hold some info about the user. One holds the data, the other one holds the controls info. Now i need to pass both of them as a parameters to a method. However they are connected to one another and i dont think that passing the 2 classes separately as parameters is okay. I wonder if i should put them in a Tuple or something that keeps them together so i can pass them as just 1 parameter to any method. Here's how they look :
The data class :
public class UsersProperties
{
public enum CUser
{
Player,
Bot1,
Bot2,
Bot3,
Bot4,
Bot5
}
public int RightCard { get; set; }
public string Name { get; set; }
public int? Chips { get; set; }
public int Type { get; set; }
public bool Turn { get; set; }
public bool FoldTurn { get; set; }
public int PreviousCall { get; set; }
public int LeftCard { get; set; }
public double Power { get; set; }
public int EnumCasted { get; set; }
}
The controls class :
public class UserControls
{
public Point CardsLocation { get; set; }
public AnchorStyles CardsAnchor { get; set; }
public Panel Panel { get; } = new Panel();
public Point PanelLocation { get; set; }
public Size PanelSize { get; } = new Size((Settings.Width + 10) * 2, Settings.Height + 20);
public int IndentationPanelXy { get; } = 10;
public Label UsernameLabel { get; set; } = new Label();
public Point UsernameLabelLocation { get; set; }
public Size UsernameLabelSize { get; } = new Size(Settings.Width * 2, 20);
public TextBox ChipsTextBox { get; set; } = new TextBox();
public Label StatusLabel { get; set; } = new Label();
public UserControls(AnchorStyles style, Point cardsLocation, bool down)
{
CardsAnchor = style;
CardsLocation = cardsLocation;
UsernameLabelLocation = down ? new Point(CardsLocation.X, CardsLocation.Y - 20) : new Point(CardsLocation.X, CardsLocation.Y + Settings.Height);
PanelLocation = new Point(CardsLocation.X - IndentationPanelXy, CardsLocation.Y - IndentationPanelXy);
}
}
Now here's how i initialize them :
private static Player Player = new Player(Properties.Settings.Default.StartingChips);
private UserControls PlayerControls = new UserControls(AnchorStyles.Bottom, new Point(560, 470),false);
And here's the method where i need to pass both of them :
private void SetPlayers(UsersProperties user, UserControls userControls, int turn, ref bool check, Image refreshbackImage)
{
if (user.Chips <= 0) return;
_foldedPlayers--;
if (turn < user.RightCard || turn > user.LeftCard) return;
if (Holder[user.RightCard].Tag != null)
{
Holder[user.LeftCard].Tag = _reserve[user.LeftCard];
}
Holder[user.RightCard].Tag = _reserve[user.RightCard];
if (!check)
{
_horizontal = userControls.CardsLocation.X;
_vertical = userControls.CardsLocation.Y;
}
check = true;
Holder[turn].Anchor = userControls.CardsAnchor;
Holder[turn].Image = refreshbackImage;
if (turn < Bot1.RightCard)
{
Holder[turn].Image = Deck[_i];
}
Holder[turn].Location = new Point(_horizontal, _vertical);
_horizontal += Holder[turn].Width;
Holder[turn].Visible = true;
Controls.Add(userControls.Panel);
userControls.Panel.Location = userControls.PanelLocation;
userControls.Panel.BackColor = Color.DarkBlue;
userControls.Panel.Size = userControls.PanelSize;
userControls.Panel.Visible = false;
if (_i != user.LeftCard) return;
check = false;
}
I want to know if there's any better way to pass 2 classes as parameters i think they should stick together anyway.
You can write a wrapper class (ie:UserContainer) which has two properties namely, usercontrol and userproperty.
Then initialize it and pass this class as parameter.
I think you could use Generics, as in here:
namespace PropertiesControls
{
public class PropsControls
{
public static void PropesAndControls<TP, TC>(TP property, TC control) where TP : UserProperties where TC: UserControls
{
//your code here
}
}
}
A generic defines a behaviour that can be applied to a class. It is used in collections, where the same approach to handling an object can be applied regardless of the type of object. I.e, a list of strings or a list of integers can be handled using the same logic without having to differentiate between both specific types.
Related
I want to populate listview with information retrieved from database using WCF in C# and am not able to retrieve correct data for listview binding.
public interface IServicePl
{
[OperationContract]
[OperationContract]
IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments();
}
[DataContract]
public class InterventiiCuEchipament
{
[DataMember]
public string EchipamentInterventie { get; set; }
public int id_interventie { get; set; }
public string tip_interventie { get; set; }
public string responsabil { get; set; }
public DateTime data_finalizare { get; set; }
public bool status { get; set; }
}
public IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments()
{
try
{
IEnumerable<InterventiiCuEchipament> query = from sel1 in dataP.interventiis
join sel2 in dataP.sesizaris
on sel1.id_interventie equals sel2.id_sesizare
select new InterventiiCuEchipament()
{
id_interventie = sel1.id_interventie,
EchipamentInterventie = sel2.echipament,
tip_interventie = sel2.tip_sesizare,
responsabil = sel1.responsabil,
data_finalizare = (DateTime)sel1.data_finalizare,
status = (bool)sel1.status
};
return query;
}
On the client side I have the following code :
if (client.InnerChannel.State != CommunicationState.Faulted)
{
List<InterventiiCuEchipament> ListaInterventii = new List<InterventiiCuEchipament>();
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();
InterventiiList.ItemsSource = ListaInterventii;
InterventiiList.Items.Refresh();
}
Output from query is ok, like in this image
Output for listview binding is like in this image
Why I can see just the count of query? and not correct values returned by query.
If the query returns values, then ListaInterventii should also have values.
I wrote a similar demo, you can compare it.
You can use foreach to see if there is a value.
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();
foreach(var a in ListaInterventii)
{
int A = a.id_interventie;
}
Demo
public class ProductService : IServicePl
{
public IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments()
{
// This comes from database.
var _dbCountries = new List<InterventiiCuEchipament>
{
new InterventiiCuEchipament {id_interventie = 1, tip_interventie="1"},
new InterventiiCuEchipament {id_interventie = 2, tip_interventie="2"},
new InterventiiCuEchipament {id_interventie = 3, tip_interventie="3"},
};
return _dbCountries;
}
}
[ServiceContract]
public interface IServicePl
{
[OperationContract]
IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments();
}
[DataContract]
public class InterventiiCuEchipament
{
[DataMember]
[Key]
public int id_interventie { get; set; }
public string tip_interventie { get; set; }
}
client side
ServicePlClient client = new ServicePlClient();
List<InterventiiCuEchipament> ListaInterventii = new List<InterventiiCuEchipament>();
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();
I need to run validation on JSON input model by taking the value from one List and check if it exists in another. This value is a rating is from 1 - 5. If there is no matching number, then it should throw an error. Below is the code and this logic goes in the section commented with : //check if rating exist in score table
namespace Alpha.Model
{
// INPUT
public class AlphaCalcParamMethod
{
public ICollection<PortfolioInputModel> portfolios { get; set; }
public Setting settings { get; set; }
public bool Validation(ref string errString)
{
// Check if portfolio exists
if(portfolios == null || portfolios.Count < 1)
{
errString = "At least 1 Portfolio.";
return false;
}
//check if weight adds upto 1
foreach(var portfolio in portfolios)
{
// var holdings = new List<PortfolioHoldingInput>();
var weightAggregator = 0.00;
foreach(var holding in portfolio.portfolioHoldings)
{
weightAggregator += holding.fundWeight;
}
if (weightAggregator != 1)
{
errString = "Fund Weights should add upto 1";
}
return false;
}
//check if rating exist in score table
foreach(var portfolio in portfolios)
{
var holdings = new List<PortfolioHoldingInput>();
var scores = new List<Setting>();
foreach(var holding in holdings)
{
//fetch the value of fundRating double
foreach(var score in scores)
{
//check if the value above exist in grossAlpha's List fundRating
// if it doesn't return false
}
}
return false;
}
return true;
}
}
// OUTPUT
public class AlphaCalcResultMethod
{
public List<PortfolioOutputModel> portfolios { get; set; }
}
public class PortfolioInputModel
{
public string portfolioIdentifier { get; set; }
public ICollection<PortfolioHoldingInput> portfolioHoldings { get; set; }
}
public class PortfolioOutputModel
{
public string portfolioIdentifier { get; set; }
public double portfolioAlpha { get; set; }
public ICollection<PortfolioHoldingOutput> portfolioHoldings { get; set; }
}
public class PortfolioHoldingInput
{
public string fundIdentifier { get; set; }
public int fundRating { get; set; }
public double fundExpenseRatio { get; set; }
public double fundWeight { get; set; }
}
public class PortfolioHoldingOutput
{
public string fundIdentifier { get; set; }
public int fundRating { get; set; }
public double fundExpenseRatio { get; set; }
public double fundWeight { get; set; }
public double fundAlpha { get; set; }
}
public class Setting
{
public List<GrossAlpha> grossAlphas { get; set; }
}
public class GrossAlpha
{
public int fundRating { get; set; }
public double grossAlpha { get; set; }
}
}
If you are going to return additional values from method, you should use out parameters.
Don't specify type of variable in variable name. I.e. instead of errorString just use error. Hungarian notation and other tricks are not needed with modern IDEs.
Double type is not precise. You should avoid comparing it to integer values for equality. Prefer greater or less than comparisons.
Use LINQ to replace loops
Method name Validation is a noun. That is pretty confusing for method which is action and should a verb. Consider rename it to Validate or IsValid
Code
public bool IsValid(out string error)
{
if (portfolios?.Any() == false)
{
error = "At least 1 Portfolio.";
return false;
}
if (portfolios.Any(p => p.portfolioHoldings.Sum(h => h.fundWeight) < 1))
{
error = "Fund Weights should add upto 1";
return false;
}
var holdings = portfolios.SelectMany(p => p.portfolioHoldings);
var validRatings = new List<int> { 1, 2, 3, 4, 5 };
if (holdings.Any(h => !validRatings.Contains(h.fundRating)))
{
error = "Fund ratings should be in " + String.Join(",", validRatings);
return false;
}
error = "";
return true;
}
Note: if valid ratings are sequential numbers, then you can just check range of fundRating value:
if (holdings.Any(h => h.fundRating < 1 || 5 < h.fundRating))
Look this code:
if(!score.grossAlphas.Exists(x => x.fundRating == holding.fundRating))
{
return false;
}
it check if exists grossAlphas with fundRating equals holding.fundRating.
put it in the loop where you want to check, let me know if it is what you want and if it works.
My structure
public struct lumCummulativeData
{
public byte[] lumId { get; set; }
public float ledPwr { get; set; }
public float batChargePwr { get; set; }
public float batDischargePwr { get; set; }
public float ledPwrAvg { get; set; }
public float batChargePwrAvg { get; set; }
public float batDischargePwrAvg { get; set; }
public float ledPwrWh { get; set; }
public float batChargeWh { get; set; }
public float batDischargeWh { get; set; }
public int count { get; set; }
public string lumName { get; set; }
}
Declaring list
public static List<lumCummulativeData> cummulativeDataList
= new List<lumCummulativeData>();
I will assign value to lumId
cummulativeData.lumId = lumIdByte;(assigned some id value)
Now i want to write some condition such that other property values of list object(same object) must be assigned based on lumId matching with lumId i get from network Packet.
Logic i tried
for(int i=0; i<cummulativeDataList.Count(); i++)
{
bool lumIdMatched = cummulativeDataList[i]
.lumIdCummulativeData
.SequenceEqual(packet.SelfID);
if(lumIdMatched == true)
{
cummulativeData.ledPwr += packet.LedPwr;
cummulativeData.batChargePwr += packet.batchrgpwr;
cummulativeData.batDischargePwr += packet.battdispwr;
cummulativeData.count++;
cummulativeDataList.Add(cummulativeData);
}
}
List object is increasing instead of adding field values to existing object .which i created while assigning LumId . i want some some logic which iterate to all the existing object's LumId and add other field values when the lumId matched with the packet lumid which i get from network
You should be using cummulativeDataList[i] instead of cummulativeData.
Also, check whether do you really need the add function. because you want to change it rather than add a new.
for (int i=0; i<cummulativeDataList.Count(); i++)
{
bool lumIdMatched = cummulativeDataList[i]
.lumIdCummulativeData
.SequenceEqual(packet.SelfID);
if (lumIdMatched == true)
{
cummulativeDataList[i].ledPwr += packet.LedPwr;
cummulativeDataList[i].batChargePwr += packet.batchrgpwr;
cummulativeDataList[i].batDischargePwr += packet.battdispwr;
cummulativeDataList[i].count++;
//cummulativeDataList.Add(cummulativeData);
}
}
I can see two issues. Firstly on your line
bool lumIdMatched = cummulativeDataList[i].lumIdCummulativeData.SequenceEqual(packet.SelfID);
lumIdCummulativeData is not a property of the lumCummulativeData struct, so it should probably be:
bool lumIdMatched = cummulativeDataList[i].lumId.SequenceEqual(packet.SelfID);
Secondly, you are adding a new list element to the cummulativeDataList whenever you match. Instead you should be modifying the list element you are currently iterating.
for(int i=0;i<cummulativeDataList.Count();i++)
{
bool lumIdMatched = cummulativeDataList[i].lumId.SequenceEqual(packet.SelfID);
if(lumIdMatched==true)
{
cummulativeDataList[i].ledPwr+= packet.LedPwr;
cummulativeDataList[i].batChargePwr += packet.batchrgpwr;
cummulativeDataList[i].batDischargePwr += packet.battdispwr;
cummulativeDataList[i].count++;
}
}
You could approach the problem in a different way using LINQ, which is somewhat more elegant:
cummulativeDataList
.Where(lumCD => lumCD.lumId.SequenceEqual(packet.SelfID))
.ForEach(lumCD => {
lumCD.ledPwr += packet.LedPwr;
lumCD.batChargePwr += packet.batchrgpwr;
lumCD.batDischargePwr += packet.battdispwr;
lumCD.count++;
}
);
I have a model structure as illustrate below.
public class GuideLineSectionsViewModel
{
public GuideLineSectionsViewModel()
{
SectionsSet = new List<SectionViewModel>();
}
public string Title { get; set; }
public List<SectionViewModel> SectionsSet { get; set; }
}
public class SectionViewModel
{
public SectionViewModel()
{
SectionsSet = new List<SectionViewModel>();
QuestionsSet = new List<QuestionViewModel>();
ProblemsSet = new List<ProblemViewModel>();
GoalsSet = new List<GoalViewModel>();
BarriersSet = new List<BarriersViewModel>();
QuestionReferencesSet = new List<QuestionReferenceViewModel>();
}
public string Heading { get; set; }
public List<SectionViewModel> SectionsSet { get; set; }
public List<QuestionViewModel> QuestionsSet { get; set; }
public List<ProblemViewModel> ProblemsSet { get; set; }
public List<GoalViewModel> GoalsSet { get; set; }
public List<BarriersViewModel> BarriersSet { get; set; }
public List<QuestionReferenceViewModel> QuestionReferencesSet { get; set; }
}
public class ProblemViewModel
{
public string Text { get; set; }
public bool Identified { get; set; }
public List<GoalViewModel> GoalsSet { get; set; }
public List<QuestionReferenceViewModel> QuestionReferencesSet { get; set; }
}
Now Based on the condition I need to update the every list value of the ProblemViewModel using linq.Below is the condition
public GuideLineSectionsViewModel FindGuidelineType(GuideLineSectionsViewModel guidelineSectionModel)
{
//GuideLineSectionsViewModel result = new GuideLineSectionsViewModel();
string title = guidelineSectionModel.Title;
int count = Regex.Matches(title, "Low Intensity").Count;
if (count > 0)
{
}
return guidelineSectionModel;
}
The guidelineSectionModel.Title will contain the text as "some value : Low Intensity". So i used the regx to filter the text. Is there other way i can directly check the condition in linq. and update the model model.
I want to update list value of ProblemViewModelmodel property value public bool Identified to "true"
Currently it contain only False value.
Please can anyone help me to solve the issue.
Have a look at following method. I could not put LINQ but I think this answer can solve your purpose. Again Some classes structure are missing in your question so you may need to put that in following method.
GuideLineSectionsViewModel FindGuidelineType(GuideLineSectionsViewModel guidelineSectionModel)
{
//GuideLineSectionsViewModel result = new GuideLineSectionsViewModel();
string title = guidelineSectionModel.Title;
int count = Regex.Matches(title, "Low Intensity").Count;
if (count > 0)
{
foreach(SectionViewModel svm in guidelineSectionModel.SectionsSet)
{
foreach(ProblemViewModel pvm in svm.ProblemsSet)
{
pvm.Identified = true;
}
}
}
return guidelineSectionModel;
}
If you prefer LINQ:
if(guideLine.Title.Contains("Low Intensity"))
{
guideLine.SectionsSet.ForEach(s => s.ProblemsSet.ForEach(ps => ps.Identified = true));
}
Note: please read this answer https://stackoverflow.com/a/2962689/1525637 due to possible performance problems with the Regex.Matches, you should use String.Contains instead.
I have a model class like this
namespace ConnectBLL.DTO.Response
{
public class CategorySettings
{
public bool NeedsLoginToViewLongText { get; set; }
public bool NeedsLoginToViewAnyDetails { get; set; }
public bool ShowAttachment { get; set; }
public string CategoryPageID { get; set; }
public string TpUrl { get; set; }
}
public class CategorySettingsListResponse
{
public List<CategorySettings> CategorySettingsList { get; set; }
}
}
And I am trying to add data to it like this
private readonly CategorySettings cs = new CategorySettings();
CategorySettingsListResponse csr=new CategorySettingsListResponse();
public string GetAllCategorySettings()
{
cs.NeedsLoginToViewLongText = true;
cs.NeedsLoginToViewAnyDetails = false;
cs.ShowAttachment = true;
cs.CategoryPageID = "1";
cs.TpUrl = "url";
csr.CategorySettingsList.Add(cs);
}
But this fails and gives an error
Object reference not set to an instance of an object.
Can any one point out what is I am doing wrong?
Somewhere, you need to initialize CategorySettingsList.
public class CategorySettingsListResponse
{
CategorySettingsListResponse() {
CategorySettingsList = new List<CategorySettings>();
}
public List<CategorySettings> CategorySettingsList { get; set; }
}
You are tying to use an instance of List before initializing. Before
csr.CategorySettingsList.Add(cs);
Insert:
if (csr.CategorySettingsList == null) {
csr.CategorySettingsList = new List<CategorySettings>();
}
You are using uncreated objects cs and CategorySettingsList, you should create them before use:
public string GetAllCategorySettings()
{
csr.CategorySettingsList = new ListCategorySettings<>();
var cs = new CategorySettings
{
NeedsLoginToViewLongText = true,
...
What is cs? Something missing?
You forgot to do this:
var cs = new CategorySettings();
Also
You need to instantiate the CategorySettingsList in constructor for CategorySettingsListResponse.