Can anybody help me to solve this problem?
I have a base class:
public class BaseShowFilter {
public int TotalCount { get; set; }
public int FromNo { get; set; }
public int ShowCount { get; set; }
public string SortFieldName { get; set; }
public bool SortAsc { get; set; }
}
and a couple of ChildClasses from this base class. Then I have a few of other classes that store in (for example)
IEnumerable<OtherClassXXX> = ....
And I want to apply some filter to all of them using same method implemented in BaseShowFilter:
For example I need
dstList = srcList.Skip(this.FromNo-1).Take(this.ShowCount);
So I need implement in BaseShowFilter one function that will be accept in parameter IEnumerable and will return also IEnumerable
How can I write it? In pure C++ it will be simple as 1,2,3... but here I don't know how can it be done. Result may be something like this:
public class BaseShowFilter {
public int TotalCount { get; set; }
public int FromNo { get; set; }
public int ShowCount { get; set; }
public string SortFieldName { get; set; }
public bool SortAsc { get; set; }
public T FilterList<T>(T SrcList) where T :IEnumerable<> {
return srcList.Skip(this.FromNo-1).Take(this.ShowCount);
}
}
This is the usual way to do it:
public IEnumerable<T> FilterList<T>(IEnumerable<T> source)
{
return source.Skip(this.FromNo - 1).Take(this.ShowCount);
}
Related
I am simply trying to generate a unique cachekey that takes in the object type and property values
GetHashCode returns different results each time so that wont work, so I have to implement a solution but it has to be fast (I can go through the properties and and concat their values to a string but this might be slow and not the best way to go about it)
Nice To Have:
so if 2 different object types have the exact same properties and same values but they are different classes, they should be different cachekeys (chances of this happening are very slim but just in case)
Here is my code
public interface ICachableRequest
{
string GetCacheKey();
}
public class Object1 : ICachableRequest
{
public int IntValue1 { get; set; }
public double DoubleVal1 { get; set; }
public string StringVal1 { get; set; }
public string GetCacheKey()
{
throw new NotImplementedException();
}
}
public class Object2 : ICachableRequest
{
public int SomeIntValue1 { get; set; }
public double SomeOtherDoubleVal1 { get; set; }
public string MoreStringVal1 { get; set; }
public string MoreStringVal2 { get; set; }
public string MoreStringVal3 { get; set; }
public string MoreStringVal4 { get; set; }
public string GetCacheKey()
{
throw new NotImplementedException();
}
}
I'm trying to create some interfaces. The IReportSection object will have one string and a collection of items, which could be different depending on what we're working with. Do I need to make it generic?
The IReport will have one string and a collection of IReportSection.
Here's how I'm trying to define it now.
public interface IReport
{
string ReportName { get; set; }
ICollection<IReportSection> ReportSections { get; }
}
public interface IReportSection
{
string ReportSectionName { get; set; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase : IReportSection
{
public string ReportSectionName { get; set; }
public ICollection ReportItems { get; set; }
}
And my models:
pulic class ProjectSubmissionViewModel
{
public int ProjectSubmissionId { get; set; }
public string SubmissionTitle { get; set; }
}
pulic class AffiliateViewModel
{
public int AffiliateId { get; set; }
public string AffiliateName { get; set; }
}
This is how I'm trying to use it in code:
public class ChapterAffiliates : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Affiliates"; } }
public ICollection<AffiliateViewModel> ReportItems { get; set; }
}
public class ChapterTitles : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Titles"; } }
public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
}
public class SubmissionListViewModel : IReport
{
public ICollection<ProjectSubmissionViewModel> Submissions { get; set; }
public ICollection<AffiliateViewModel> Affiliates{ get; set; }
public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections
{
get
{
var affiliateSection = new ChapterAffiliates
{
ReportItems = Affiliates
};
var titleSection = new ChapterTitles
{
ReportItems = Submissions.Where(s => s.SubmissionTitle.Contains("SomePhrase")).ToList()
};
var sections = new List<IReportSection> { {subSection}, {titleSection} };
return sections;
}
}
}
I'm not sure how to best define this. I'm pretty sure I've done it before, but it's not coming to me.
Are the type parameters for TRType all the same within a certain report? E.g. will you have report sections with different report types in them?
If all types within a report are the same, the solution is relatively simple:
public interface IReport<T> { ... }
If this is not the case - you'll have to do something different, e.g:
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase<TRType> : IReportSection {
...
}
This allows you to put different underlying types in the ReportSections collection related to the report. You'll have to do some more work to get the exact information that you need out of each report section.
I have some classes which only serve to contain data. For example
public class EntityAdresse : IEntityADRESSE
{
public string Name1 { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string NatelD { get; set; }
public string Mail { get; set; }
public int Id_anrede { get; set; }
public string Telefon { get; set; }
public int Id_adr { get; set; }
public int Cis_adr { get; set; }
}
This represents a address. Like I said, it only contains data. No Methods (I know the interface doesn't make sense here...)
Now I need to implement ToString for all this Entity-Classes and there are a lot of them.
My question is: Is there a metaprograming feature in C# which generates this tostring methods automaticaly? I don't want to write boiler plate code for every which of these classes.
Alternatively I could also write a perl or python script to generate the code. But I prefer doing it in C# directly.
Generally, you need to obtain all property values of your class and combine them into a single string. This can be done using the following approach:
public override string ToString()
{
PropertyDescriptorCollection coll = TypeDescriptor.GetProperties(this);
StringBuilder builder = new StringBuilder();
foreach(PropertyDescriptor pd in coll)
{
builder.Append(string.Format("{0} : {1}", pd.Name , pd.GetValue(this).ToString()));
}
return builder.ToString();
}
The feature is called reflection. A simplest example would be:
public class EntityBase
{
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach ( var property in this.GetType().GetProperties() )
{
sb.Append( property.GetValue( this, null ) );
}
return sb.ToString();
}
}
public class TheEntity : EntityBase
{
public string Foo { get; set; }
public string Bar { get; set; }
}
Please finetune it to fulfill your requirements.
As you can see the idea is to have a single implementation in a base class so that all descendands automatically inherit the same behavior.
A short version of what's already been said:
public override string ToString()
{
var propertyStrings = from prop in GetType().GetProperties()
select $"{prop.Name}={prop.GetValue(this)}";
return string.Join(", ", propertyStrings);
}
There isn't a feature built into the language to do this automatically, but you could write a library to do it using the Expression features in the framework to generate a function to do it.
You'd have a function like this:
Func<T,string> GenerateToString<T>()
And in your class you have something like this:
public class EntityAdresse : IEntityADRESSE
{
private static readonly Func<EntityAdresse,string> s_ToString=Generator.GenerateToString<EntityAdresse>();
public string Name1 { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string NatelD { get; set; }
public string Mail { get; set; }
public int Id_anrede { get; set; }
public string Telefon { get; set; }
public int Id_adr { get; set; }
public int Cis_adr { get; set; }
public override ToString()
{
return s_ToString(this);
}
}
The challenge is writing GenerateToString. Using the Expression framework and reflection you'll be able to create a delegate that is as efficient as if you'd written the code by hand.
You could use reflection on it's own, but the performance hit will soon start to be an issue.
There is an open source framework StatePrinter for automatic ToString generation. It is very configurable so it should cater for your needs. The introspection code can be found at Introspection
How can I have a property which can accept object of any type (of class)... something like this?
public class HttpConnectorRequest
{
public int Id { get; set; }
public T RequestObject { get; set; } where T: class
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
I am trying to acheive an alternative for something like this:
public class HttpConnectorRequest
{
public int Id { get; set; }
public ClassA ClassARequestObject { get; set; }
public ClassB ClassBRequestObject { get; set; }
public ClassC ClassCRequestObject { get; set; }
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
That's fine - you just need to make it generic:
public class HttpConnectorRequest<T> where T: class
{
public int Id { get; set; }
public T RequestObject { get; set; }
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
Then you'd write something like:
var request = new HttpConnectorRequest<string>();
request.RequestObject = "Hello!";
Generics is a big topic - MSDN is probably a reasonable starting point, although I suspect you'll want to read about it in a tutorial or book at some point. (While my own book, C# in Depth, obviously covers generics, plenty of others do too :)
Note that this makes the whole type generic. If you want to make just a single property generic, you're out of luck... although you could make a method generic:
public class HttpConnectorRequest
{
// Other members elided
public void SetRequestObject<T>(T value) where T : class
{
...
}
public T GetRequestObject<T>() where T : class
{
...
}
}
Quite what this would do is up to you - bear in mind that someone could write:
var request = new HttpConnectorRequest();
request.SetRequestObject<string>("Hello");
var button = request.GetRequestObject<Button>();
This is my set up,
class CostPeriodDto : IPeriodCalculation
{
public decimal? a { get; set; }
public decimal? b { get; set; }
public decimal? c { get; set; }
public decimal? d { get; set; }
}
interface IPeriodCalculation
{
decimal? a { get; set; }
decimal? b { get; set; }
}
class myDto
{
public List<CostPeriodDto> costPeriodList{ get; set; }
public List<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList; // compile error
}
}
}
What would be the best way of doing this?
Use Cast<IPeriodCalculation>() :
public class CostPeriodDto : IPeriodCalculation
{
public decimal? a { get; set; }
public decimal? b { get; set; }
public decimal? c { get; set; }
public decimal? d { get; set; }
}
public interface IPeriodCalculation
{
decimal? a { get; set; }
decimal? b { get; set; }
}
public class myDto
{
public List<CostPeriodDto> costPeriodList { get; set; }
public List<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList.Cast<IPeriodCalculation>().ToList();
}
}
}
I believe in C#4, if you were using something implementing IEnumerable<out T>, you could simply do it the way you wrote it, and it would be resolved using Covariance.
class myDto
{
public IEnumerable<CostPeriodDto> costPeriodList{ get; set; }
public IEnumerable<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList; // wont give a compilation error
}
}
}
Try return this.costPeriodList.Cast<IPeriodCalculation>().ToList().
The LINQ methods to cast from one sequence to another will not be equal. That is to say that the following test would fail if you used Cast()/ToList().
Assert.AreSame(myDto.costPeriodList, myDto.periodCalcList);
Furthermore, using those methods means that if you tried to add an item to one collection, they would not be reflected in the other. And every time you called periodCalcList, it would be creating an entirely new collection which could be disastrous depending on how many items, how frequently it's called, etc.
A better solution, in my opinion, is to not use List<T> for holding the CostPeriodDto and instead use a collection derived from Collection<T> and explicitly implement IEnumerable<IPeriodCalculation>. Optionally you could implement IList<IPeriodCalculation> if you needed to.
class CostPeriodDtoCollection :
Collection<CostPeriodDto>,
IEnumerable<IPeriodCalculation>
{
IEnumerable<IPeriodCalculation>.GetEnumerator() {
foreach (IPeriodCalculation item in this) {
yield return item;
}
}
}
class MyDto {
public CostPeriodDtoCollection CostPeriods { get; set; }
public IEnumerable<IPeriodCalculation> PeriodCalcList {
get { return CostPeriods; }
}
}