List all method parameters automatically to pass them forward - c#

As the code illustrates, passing down parameters is a rather frequent task. Instead of writing them by hand, is there a way to auto-generate the list isPriority, label, id, start, user with Resharper, Visual Studio natively, or another add-on?
public void TransformAndStore(
bool isPriority,
string label,
string id,
DateTimeOffset start,
string user)
{
if (this.IsValid(id)) {
label = this.Clean(label);
this.Reposit(isPriority, label, id, start, user);
}
}
The list generated should be based on the method signature, listing all parameters of the method without their types, in the order they appear.
Additionally, if the Reposit method were to use some but not all of the same parameters available in the calling method scope, as identified by parameter/variable names, then autocompleting that would speed up coding as well, and reduce RSI :)

You could create a class to store all the parameters so you only need to pass a single item around. Resharper can do this for you automatically by using Refactor -> Extract -> Extract class from parameters.
Also if you are always repeating the same groups of parameters, consider moving the methods that act upon them into the class too. Logically grouping the data with the methods can be a good practice. For example:
public class CleverName
{
public bool IsPriority { get; set; }
public string Label { get; set; }
public string Id { get; set; }
public DateTimeOffset Start { get; set; }
public string User { get; set; }
public bool IsValid()
{
//Check if Id is valid
}
public void TransformAndStore()
{
if (this.IsValid()) {
Label = this.Clean(Label);
this.Reposit();
}
}
public void Reposit()
{
}
}

While it doesn't answer the exact question you're asking, take a look at ReSharper's Smart Completion. It will filter the available items for completion based on the current context, and is often really good at suggesting exactly the right parameter to pass through.

Related

Generic way to access class properties

I have been trying to read the value from the excel sheet, map it into a dataTable and then map the value to its class in C# using reflection. There is no issue for this
I have two classes- one providing test data, and another one providing the logic to read a fixed-width file.
When the two classes have more properties, the way i access to its properties somehow duplicating.
Here is the TestData class
class TestData
{
public string TestName { get; set; }
public string Name{ get; set; }
public string Address{ get; set; }
}
//ignoring the whole logic in the middle, i can access the value of the test by
_testData.Name or _testData.Address
Here is the class to access fixed-width file
class FieldPosition
{
public string FieldName { get; set; }
public string PosStart{ get; set; }
public string PosEnd{ get; set; }
}
class IncomingFields
{
public FieldPosition Name => GetValue("Name");
public FieldPosition Address=> GetValue("Address");
}
//ignoring the whole logic in the middle, i can access the value of the field position by
_field.Name.PosStart or _field.Name.PosEnd
When TestData and IncomingFields have more properties, the code to call them becomes a big duplicating mess. Is there any way to reduce the code since the property name is the same?
Here is what i have to do per one property.
if (_testData.Name != "")
{
ModifyFixedWidthFile(_testData.Name, _field.Name.PosStart, _field.Name.PosEnd)
}
if (_testData.Address!= "")
{
ModifyFixedWidthFile(_testData.Address, _field.Address.PosStart, _field.Address.PosEnd)
}
Is there anyway to reduce 2 if conditions, into 1 block of code by doing a foreach loop? I just don't know how to call the properties in a generic way. is it possible to do something like this in c#
if (_testData.[something generic]!= "")
{
ModifyFixedWidthFile(_testData.[something generic], _field.[something generic].PosStart, _field.[something generic].PosEnd)
}
My names for methods and arguments are all close to useless here.
void OuterMethod(TestData testData, IncomingFields fields)
{
ModifySomething(testData.Address, fields.Address);
ModifySomething(testData.Name, fields.Name);
}
void ModifySomething(string value, FieldPosition fieldPosition)
{
if (value != "")
ModifyFixedWithFile(value, fieldPosition.PosStart, fieldPosition.PosEnd);
}
This just breaks it into two functions. The outer method selects a string property from testData and selects a FieldPosition property from fields. Those are the only parts that are changing. Then it calls the inner ModifySomething method which acts on those values.

Dynamically Add Values from Property

I was wondering if I can dynamically add values set in property using override method. I want to add the values (scores) from properties so that in the end, I can get the total points.
here my code
public abstract class player
{
public string nickName { get; set; }
public virtual int computeScore()
{
throw new NotImplementedException();
}
}
public class Bes : player
{
public int initScore =0;
public int score { get; set; }
public int ttlScore { get; set; }
public override int computeScore()
{
return this.ttlScore += this.score;
}
}
It's doubtful that want you want to do is a good idea. But the fact is, it's not really clear what you want to do.
I have a vague sense that you want, every time the score property is set, to add the value to the ttlScore property. If so, then sure...you can do that, but it's a terrible idea. Using a property to represent that operation would be extremely confusing; instead, you should have a method, e.g. named AddScore(), so it's clear reading the code that every time a score is passed to the method, it will be added to the running total.
For example, something like this:
public class Bes : player
{
public int MostRecentScore { get; private set; }
public int TotalScore { get; private set; }
public int AddScore(int score)
{
this.MostRecentScore = score;
return this.TotalScore += score;
}
}
Then the MostRecentScore property will still show whatever the most recent score was, while the TotalScore property will show the running total, but the class members make it clear that you must call AddScore() to report a new score, and that this will take care of updating both properties of interest.
This example of course does not use the virtual aspect of your code example. It's not clear from your question why the computescore() method was in fact made virtual, and it probably doesn't need to be — if you really want the base class to know about scoring, then the score-related properties belong there as well, and none of the members need to be virtual — so I've left it out.
If this does not address your question, please edit your question so that it's more clear what you're trying to do. Provide a good Minimal, Complete, and Verifiable code example that shows clearly what you've tried, along with a detailed and specific explanation of what the code does, and what you want it to do instead.

How to let an Attribute in property 'A' know the existence of property 'B'?

How to let an Attribute in one property know the existence of another property?
Lets say i have this class, and like this, many others:
public class MyClass
{
[CheckDirty] //a custom attribute (that it is empty for now)
public int A { get; set; }
public int B { get; set; }
public string Description { get; set; }
public string Info { get; set; }
}
Somewhere in our program, if we want to see if an object changed values on any CheckDirty property, for example lets say it is diferent from DB, MyPropertyUtils.GetPropertiesIfDirty() does this, giving us an array of changed propertys, on any property with that attribute:
PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues);
Perfect.
So, lets say A changed and in this case Info holds some information we need(in another class might be any other property). If we want 'A' we just do property.GetValue(NewValues, null);
But we dont want 'A's value, we want 'A' or CheckDirty to tell us where to read some data we want. How can i tell my attribute CheckDirty where to get the values from?
I was thinking in giving an expression to CheckDirty but an Attribute's argument "must be a constant expression, typeof expression or array creation expression of an attribute parameter type"(thats what VS says).
So I decided, "ok, lets give it a string with the property's name", and so my try failed:
(this is all the code we need to work on, the rest was just to give some kind of context example)
public class CheckDirty : Attribute
{
public String targetPropertyName;
public CheckDirty(String targetPropertyName)
{
this.targetPropertyName = targetPropertyName;
}
}
public class MyClass
{
//Code fails on this line
[CheckDirty(BoundPropertyNames.Info)]
public int Id { get; set; }
public string Info { get; set; }
public static class BoundPropertyNames
{
public static readonly string Info = ((MemberExpression)
((Expression<Func<MyClass, string>>)
(m => m.Info)
).Body
).Member.Name;
}
}
This is the error i get:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
We do NOT want to pass the name of the proprety as a String saing [CheckDirty("Info")] because that way if anyone in the future changes the class, and in concrete the property's name, no error would get thrown in compile time by it, only occuring the error in run time, when an "edit" to that field would occur. Or maybe it would just not do anything because it could not find the property.
Any idea how to not use the strongly typed string as a property name?
You may use something like this, first declare an interface that will be implemented by every class that need dirty checking:
interface IDirtyCheckPropertiesProvider {
string GetPropertyName(string dirtyProperty);
}
then implement it like that
class DataEntity : IDirtyCheckPropertiesProvider {
[CheckDirty]
public int Id { get; set; }
public string Info { get; set; }
string GetPropertyName(string dirtyProperty) {
if (GetPropertyNameFromExpression(x => Id) == dirtyProperty)
return GetPropertyNameFromExpression(x => Info);
return null;
}
}
In class that will be responsible for handling dirty checks you must use this interface to get target property names.
There is a bit too much boilerplate that may be removed further by using Reflection API.
On the other hand using string for property names looks like more simple solution. If you use tool like Resharper - using string is a viable option - Resharper will automatically refactor string when you change property name.
Also for a long time string'ed property names were used in implementation of WPF INotifyPropertyChanged.
As comments suggested nameof is the best option in VS2015.

How to pass data between function calls

We can pass data between functions by using class objects. Like i have class
public class AddsBean
{
public long addId{get;set;}
public int bid { get; set; }
public long pointsAlloted { get; set; }
public string userId { get; set; }
public enum isApproved { YES, NO };
public DateTime approveDate { get; set; }
public string title { get; set; }
public string description { get; set; }
public string Link { get; set; }
public DateTime dateAdded { get; set; }
}
We can call function like public List<AddsBean> getAdds(string Id). This approach is good when you need all the variables of class. But what if you need only 2 or 3 variables of class?
Passing object of class is not good because it will be wastage of memory. Another possible solution is to make different classes of lesser variables but that is not practical.
What should we do that will best possible solution to fulfill motive and best according to performance also?
In Java - "References to objects are passed by value".. So, you dont pass the entire object, you just pass the reference to the object to the called function.
EG:
class A{
int i;
int j;
double k;
}
class B{
public static void someFunc(A a) // here 'a' is a reference to an object, we dont pass the object.
{
// some code
}
public static void main(String[] args){
A a = new A();
B.someFunc(a); // reference is being passed by value
}
}
first of all, as Java is pass by value and references typed, there is no need to worry about the memory wastage.
next, as you have mentioned, it is not good to pass all the object if you do not need them all, in some situation, it's true. as you need to protect your data in instance, thus you can use different granularity of class, for instance:
class A
{id, name}
class B extends A
{password,birthday}
by refer to different class you can control the granularity yourself, and provide different client with different scope of data.
But in some condition, you need to use a instance to store all data in the whole application, like configure data in hadoop, or some other configuration related instance.
Try to choose the most suitable scope!
If you're sure that this is the source of problems and you don't want to define a new class with a subset of the properties, .NET provides the Tuple class for grouping a small number of related fields. For example, a Tuple<int, int, string> contains two integers and a string, in that order.
public Tuple<string, long, DateTime> GetPointsData()
{
AddsBean bean = ... // Get your AddsBean somehow
return Tuple.Create<string, long, DateTime>(bean.userId, bean.pointsAlloted, bean.approveDate);
}
Once this method goes out of scope, there is no longer a live reference to the object bean referred to and will be collected by the garbage collector at some point in the future.
That said, unless you're sure that instances of the AddsBean class are having a noticeable negative effect on the performance of your app, you should not worry about it. The performance of your application is probably affected far more by other operations. Returning a reference type (a type defined with class instead of struct) only passes a reference to the object, not the data of the object itself.

`Type.GetProperties` property order

Short Version
The MSDN documentation for Type.GetProperties states that the collection it returns is not guaranteed to be in alphabetical or declaration order, though running a simple test shows that in general it is returned in declaration order. Are there specific scenarios that you know of where this is not the case? Beyond that, what is the suggested alternative?
Detailed Version
I realize the MSDN documentation for Type.GetProperties states:
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
so there is no guarantee that the collection returned by the method will be ordered any specific way. Based on some tests, I've found to the contrary that the properties returned appear in the order they're defined in the type.
Example:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Simple Properties:
FieldB
FieldA
FieldC
One such case that this differs only slightly is when the type in question has a parent who also has properties:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC
Which means the GetProperties method walks up the inheritance chain from bottom up when discovering the properties. That's fine and can be handled as such.
Questions:
Are there specific situations where the described behavior would differ that I've missed?
If depending on the order is not recommended then what is the recommended approach?
One seemingly obvious solution would be to define a custom attribute which indicates the order in which the properties should appear (Similar to the Order property on the DataMember attribute). Something like:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}
And then implement such as:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}
But as many have found, this becomes a serious maintenance problem if your type has 100 properties and you need to add one between the first 2.
UPDATE
The examples shown here are simply for demonstrative purposes. In my specific scenario, I define a message format using a class, then iterate through the properties of the class and grab their attributes to see how a specific field in the message should be demarshaled. The order of the fields in the message is significant so the order of the properties in my class needs to be significant.
It works currently by just iterating over the return collection from GetProperties, but since the documentation states it is not recommended I was looking to understand why and what other option do I have?
The order simply isn't guaranteed; whatever happens.... Happens.
Obvious cases where it could change:
anything that implements ICustomTypeDescriptor
anything with a TypeDescriptionProvider
But a more subtle case: partial classes. If a class is split over multiple files, the order of their usage is not defined at all. See Is the "textual order" across partial classes formally defined?
Of course, it isn't defined even for a single (non-partial) definition ;p
But imagine
File 1
partial class Foo {
public int A {get;set;}
}
File 2
partial class Foo {
public int B {get;set:}
}
There is no formal declaration order here between A and B. See the linked post to see how it tends to happen, though.
Re your edit; the best approach there is to specify the marshal info separately; a common approach would be to use a custom attribute that takes a numeric order, and decorate the members with that. You can then order based on this number. protobuf-net does something very similar, and frankly I'd suggest using an existing serialization library here:
[ProtoMember(n)]
public int Foo {get;set;}
Where "n" is an integer. In the case of protobuf-net specifically, there is also an API to specify these numbers separately, which is useful when the type is not under your direct control.
For what it's worth, sorting by MetadataToken seemed to work for me.
GetType().GetProperties().OrderBy(x => x.MetadataToken)
Original Article (broken link, just listed here for attribution):
http://www.sebastienmahe.com/v3/seb.blog/2010/03/08/c-reflection-getproperties-kept-in-declaration-order/
I use custom attributes to add the necessary metadata myself (it's used with a REST like service which consumes and returns CRLF delimited Key=Value pairs.
First, a custom attribute:
class ParameterOrderAttribute : Attribute
{
public int Order { get; private set; }
public ParameterOrderAttribute(int order)
{
Order = order;
}
}
Then, decorate your classes:
class Response : Message
{
[ParameterOrder(0)]
public int Code { get; set; }
}
class RegionsResponse : Response
{
[ParameterOrder(1)]
public string Regions { get; set; }
}
class HousesResponse : Response
{
public string Houses { get; set; }
}
A handy method for converting a PropertyInfo into a sortable int:
private int PropertyOrder(PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
Even better, write is as an extension:
static class PropertyInfoExtensions
{
private static int PropertyOrder(this PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
}
Finally you can now query your Type object with:
var props = from p in type.GetProperties()
where p.CanWrite
orderby p.PropertyOrder() ascending
select p;
Relying on an implementation detail that is explicitly documented as being not guaranteed is a recipe for disaster.
The 'recommended approach' would vary depending on what you want to do with these properties once you have them. Just displaying them on the screen? MSDN docs group by member type (property, field, function) and then alphabetize within the groups.
If your message format relies on the order of the fields, then you'd need to either:
Specify the expected order in some sort of message definition. Google protocol buffers works this way if I recall- the message definition is compiled in that case from a .proto file into a code file for use in whatever language you happen to be working with.
Rely on an order that can be independently generated, e.g. alphabetical order.
1:
I've spent the last day troubleshooting a problem in an MVC 3 project, and it all came down to this particular problem. It basically relied on the property order being the same throughout the session, but on some occations a few of the properties switched places, messing up the site.
First the code called Type.GetProperties() to define column names in a dynamic jqGrid table, something that in this case occurs once per page_load. Subsequent times the Type.GetProperties() method was called was to populate the actual data for the table, and in some rare instances the properties switched places and messed up the presentation completely. In some instances other properties that the site relied upon for a hierarchical subgrid got switched, i.e. you could no longer see the sub data because the ID column contained erroneous data. In other words: yes, this can definitely happen. Beware.
2:
If you need consistent order throughout the system session but not nessecarily exactly the same order for all sessions the workaround is dead simple: store the PropertyInfo[] array you get from Type.GetProperties() as a value in the webcache or in a dictionary with the type (or typename) as the cache/dictionary key. Subsequently, whenever you're about to do a Type.GetProperties(), instead substitute it for HttpRuntime.Cache.Get(Type/Typename) or Dictionary.TryGetValue(Type/Typename, out PropertyInfo[]). In this way you'll be guaranteed to always get the order you encountered the first time.
If you always need the same order (i.e. for all system sessions) I suggest you combine the above approach with some type of configuration mechanism, i.e. specify the order in the web.config/app.config, sort the PropertyInfo[] array you get from Type.GetProperties() according to the specified order, and then store it in cache/static dictionary.

Categories

Resources