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 have a xml format in following format mentioned below:-
<JobRunnerPluginStaus PluginName="JobRun">
<JobstepStatus>
<JobStatus StepNumber="1" StepStatus="Done"/>
<JobStatus StepNumber="2" StepStatus="Started" />
</JobstepStatus>
</JobRunnerPluginStaus>
I want to get it converted to following class object using Generics and Reflection.
I want to convert the attributes to simple type(PluginName) and the nested property to a list object(JobstepStatus).
public class JobRunnerPluginStaus
{
public List<JobStatus> JobstepStatus { get; set; }
public string PluginName { get; set; }
}
public class JobStatus
{
public int StepNumber { get; set; }
public string StepStatus { get; set; }
}
I mostly use sites like: https://xmltocsharp.azurewebsites.net/
to do the dirty work for me.
Below is how your class hierarchy would look like:
[XmlRoot(ElementName="JobStatus")]
public class JobStatus {
[XmlAttribute(AttributeName="StepNumber")]
public string StepNumber { get; set; }
[XmlAttribute(AttributeName="StepStatus")]
public string StepStatus { get; set; }
}
[XmlRoot(ElementName="JobstepStatus")]
public class JobstepStatus {
[XmlElement(ElementName="JobStatus")]
public List<JobStatus> JobStatus { get; set; }
}
[XmlRoot(ElementName="JobRunnerPluginStaus")]
public class JobRunnerPluginStaus {
[XmlElement(ElementName="JobstepStatus")]
public JobstepStatus JobstepStatus { get; set; }
[XmlAttribute(AttributeName="PluginName")]
public string PluginName { get; set; }
}
I have this json
{
"query":{
"allcategories":{
"accontinue":"!!!_songs"
}
}
}
here are the c# classes:
public class Allcategories
{
public string accontinue { get; set; }
}
public class Query
{
public Allcategories allcategories { get; set; }
}
public class RootObject
{
public Query query { get; set; }
}
can i map this somehow the following C# classes? I want to skip one level, and reduce nesting of json like this:
public class Query
{
[JsonAttribute("allcategories.accontinue")]
public string accontinue { get; set; }
}
public class RootObject
{
public Query query { get; set; }
}
Your suggested code is valid and would reduce nesting, but accontinuewould no longer be an Allcategories object, it would be a string attribute of Query.
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
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);
}