This question already has answers here:
How can I get the name of a variable passed into a function?
(23 answers)
Closed 8 years ago.
One thing to note is: I need to get the variable's name, not the property's name.
I have a scenario where I need to pass in either List<int> or List<double> to a view. So in the partial view I bind the model to dynamic:
#model dynamic
var nameOfParameter = Web.Controllers.MemberInfoGetting.GetMemberName(() => Model);
#foreach (var value in list)
{
<td>#Html.Editor(value, "DoubleTemplate", new { Column = count, Switcher = (YearOfProgram >= count)})</td>
sum += (double)value;
++count;
}
And this is how I call the partial view from the main view:
#Html.Partial("_myPartial", Model.CategoryList)
Then I found that I have to know the name(CategoryList) of the list which is passed into the partial view.
Here I found many posts talking about using something like this:
public static class MemberInfoGetting
{
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
}
}
This code doesn't work for me as the result of (nameOfParameter )calling it will always be "Model", rather than "CategoryList".
So, is it possible to achieve what I want?
Update1
The reason why I need to pass in the name of the list is because I need the name of the list to form the name on the html element into something like: CategoryList_1. So Razor knows I am trying to bind the value of the textbox into the 1st element of a property in my view model.
class MyViewModel
{
................
public List<double> CategoryList {get; set;}
................
}
Update2
#Html.RenderPartial("_VerificationSummarySection",new { ListName = "PracticeEvaluationCreditsVerifiedList", List = Model.PracticeEvaluationCreditsVerifiedList})
I'm now trying to pass in the name of the list by using RenderPartial. But, I cannot find the right way to use it.
Names are relative. The list itself doesn't have a name.
One thing to notice is : I need to get the variable's name, not the property's name.
In your use of the method:
var nameOfParameter = Web.Controllers.MemberInfoGetting.GetMemberName(() => Model);
The name here is Model, and Model is the property; it isn't a variable. You have obtained the name of the property: "Model". You cannot, however, obtain the name as it would have been in a calling context (even in regular C# this is hard; between views, however, it is essentially impossible).
As an aside, with that GetMemberName method, if you did use it to obtain the name of a variable, in IL terms it would actually cease being a variable, and would instead become a field - because that is how "captured variables" are implemented by the compiler.
You should instead make it possible to pass down the name you want; either as additional context on the view, or as a view-model that encapsulates a list and a name, or by creating a "named list" concept (perhaps by subclassing List<T> or similar, or by adding an INamedList interface).
Related
So currently, you can imagine I have 1 method that is the constructor that funcitons like
info.PersonalInfo=getPersonalInfo(Id);
info.MedicalInfo=getMedicalInfo(Id);
Thing is, all of those get data and get binarys are repeating 95% of the code
using (CVDataEntities data = new CVDataEntities())
{
var temp = data.PersonalInfo.Where(m => m.Id == Id).FirstOrDefault();
return temp;
}
The only thing that changes is instead of PersonalInfo its MedicalInfo.
I thought of using a switch and just sending a number as the selector for which specific object I would want.
But the problem is the method is made so that it can only return
public IEnumerable<PersonalInfo> getPersonalInfo (string Id)
Is there any way for me to make a IEnumerable that lets me return any object, or is there a better way to go about this. I want to do it mostly to reduce the code from 400 lines down to 200 at most.
Try using generic methods, you will be able to specify the return type of your function when you call it. This could make your code look like this :
public IEnumerable<T> getInfo<T>(string id)
{
// Some code
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id);
info.MedicalInfo = getInfo<MedicalInfo>(Id);
But be careful while using it, cause the compiler won't know what type T is (it is only defined at runtime) so it could lead to some errors while processing the data (like missing properties / methods exclusive to a specific type)
EDIT : Johnathan Barclay made a good point by commenting that the // some code bit is relevant and asked "How would the correct property be selected on data? How do you access an Id property on T?"
To get the correct property and access an Id property, you could use System.Reflection and add a string parameter to get the name of the property you want to use, and another to give the Id property name to the function:
public IEnumerable<T> getInfo<T>(string id, string propertyToReadName, string propertyToCompareName)
{
using (CVDataEntities data = new CVDataEntities())
{
// Getting the enumerable not filtered first
IEnumerable<T> unfilteredList = (IEnumerable<T>)data.GetType() // Get the type
.GetProperty(propertyToReadName, typeof(T)) // Get the property (PersonalInfo or MedicalInfo)
.GetValue(data); // Get the value of this property in the `data` instance
// Filtering the list
IEnumerable<T> filteredList = unfilteredList.Where(m =>
typeof(T).GetProperty(propertyToCompareName) // Get the "id" property using parameter
.GetValue(m) // Get the "id" value of m instance
.Equals(id)); // Check if it equals the id given as parameter
return filteredList;
}
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id, "PersonalInfo", "Id");
info.MedicalInfo = getInfo<MedicalInfo>(Id, "MedicalInfo", "Id");
If you want to return a single element instead of an IEnumerable don't forget to change the return type of the function from IEnumerable<T> to T and add .FirstOrDefault() at the return line
Note that you could also give another value to the parameter propertyToCompareName and make a comparison to another property of the T class
Okay, what do I need?
I'm looking for a class (object by schema instance), which has a maximal number of hard defined fields. And a dynamic way to "use" (create, read, update, delete) a "sub-object" of it.
Like this:
public class Books
{
public int Id;
public string Title;
public string Isbn;
public int Pages;
public int Price;
public string Author;
public string DescriptionSmall;
public string DescriptionLong;
public string Publisher;
//create constructor:
public Books(int id, string title, string isbn, ...) {
Id = id,
Title = title,
Isbn = isbn,
...
//only the setted fields should be usable
}
//add fields (only pre-defined should be possible)
public void|bool Add(Dictionary<string, object>) { //or List<> overload for only field names (without values)
//add fields
}
//get a return (only pre-defined should be possible)
public void|bool return Get(Dictionary<string, object>) {
//return as a sub-object
}
//delete void|bool fields
public Delete(Dictionary<string, object>) {
//delete fields
}
//update fields
public Update(...) {
...
}
}
//and than I can use it like a object, createtd by instance or what ever. :/
var smallBooks = new Books(id = 1, Title = "Lord of tha weed"); //can use all methods but for the moment only the created fields, but can add more fields by add()...
I dislike to have hunderds of models/entites for all possible field-combinations.
The problem is, that I try to update a database via GraphQL server.
Is there a way to return a part of the object, which is a "sub-" object, itself?
Yeah I know, I also can create a dynamic obejct with help by ExpandoObject or create a Collection/Dictionary to send.
It's important, that the not used fields are not only NULL, because some fields in my database are nullable and can work with NULL as a value.
-------------------------[Addition: 2021-07-27]-------------------------
Okay, I obviously expressed myself ambiguously. I have a table in the DB and the fields in it are firmly defined. When updating data, however, I only need a few fields from the complete list of all fields. The problem, I would like to keep the selection of the fields dynamic instead of having to create numerous entities or DTOs as part of the main model.
I'm looking for a simple way to create a dynamic sub-object in the code that contains the same methods, but only a (freely selectable) selection of the total fields.
Within my project it happens from time to time that data should be collected and processed before that data is finally sent to the server as a dynamic subset, e.g. as an update (GraphQL update mutation). An existing data set (main model) should, as it were, reflect the current status of the database. But only individual fields are required for an update.
I just want to avoid having to create countless classes for all combinations and choices.
Is there a way to derive a dynamic partial selection from the main class, which, for example, only contains 1 to x fields, but possibly has a reference to the main class and its fields (sync). - So an instance from the main class and dynamically derive further sub-objects from this object.
I used to simply create a dictionary<string, object> with field names and values and use mainDict.GetKeys() or mainDict.Select(f => f.key / f.value) from this selection in a complex method to create a "small copy" to update only separate fields (via uploading to the server). - But I'd like to use oop with classes, instances and maybe dynamic objects (expando objects). - But I don't know how. ;) Sorry.
I'm open to any suggestion. If possible, simple and with little code, but as dynamic as possible.
To expand on my comment. A more complex would be like this:
In this example the Course has some fixed number of fields but expands on that using the CouresField (many-to-many) connection to connect several FormFields. The FieldValue entity holds the values for the fields in combination with the UserFieldValue (many-to-many) for each user (in this case).
Now maintaining all of this is a lot of work but you can use the EntityFramework to maintain the many-to-many connections for you. No need to do all the coding yourself. It will be automatically generated.
I have a class:
public class ClassA
{
string Field1;
int Field2;
ObservableCollection<ClassB> col1;
ObservableCollection<ClassC> col2;
ObservableCollection<ClassD> col3;
ObservableCollection<ClassE> col4;
ObservableCollection<ClassF> col5;
// ...
}
In my application, when the user hits save I need to loop through this class and perform actions with each of its members.
I can use reflection to go through the normal fields, but not sure how to:
get each of the collections
identify what type it holds
loop its items and cast each collection item to its Type so can work with it.
Background:
I have multiple datagrids on a wpf app, with the class structure above being the viewModel datacontext.
When user hits save I need to do save each item in the viewmodel to its own relevant table in the database via stored procs.
Once I have the a collection I need to test IF "is a class b" or IF "is a class C" and then use the particular method on it, with that method receiving the actual Type.
Would be much cleaner than hardcoding the class.
Reflection can be used to interrogate a type hierarchy at run-time, however this quickly becomes painful if you're trying to do so with generics, more so if you think you can access the type at runtime as you would at compile-time.
The code below demonstrates the principal behind (1) and (2) in your question. (3) is harder to answer without more detail on how you wish to use the generic types contained in each ObservableCollection.
var instance = new ClassA();
var fields = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach(var field in fields)
{
Console.WriteLine("Field name: {0}. Type:{1} IsGeneric:{2}", field.Name, field.FieldType.Name, field.FieldType.IsGenericType);
if(field.FieldType.IsGenericType)
{
var genericArgs = field.FieldType.GenericTypeArguments;
foreach(var genericArg in genericArgs)
{
Console.WriteLine("\tGenericArg Type:{0}", genericArg.Name);
}
}
}
Live demo: http://rextester.com/AJVS85556
I am trying to understand the DynamicDictionary in NancyFX, it looks pretty cool. Does anyone know of a blog post or similar, that goes through the internals of it?
I need a propertybag to pass around objects, that I don't know the content of because they come from outside my system as JSON. But based on the contents of these objects, such as the presence of certain properties I need to do stuff.
I could just pass around dynamic objects, but that is a bit too vague I think. Don't really like that.
I would need nested dictionaries, to fully represent the object graph.
The dynamic dictionary is just a ExpandoObject with a Dictionary in it. So it can still be accessed like a dictionary.
For example, in MVC you access Form properties like so:
var name = Request["name"];
or
var name = Request.Form["name"];
When a request comes into Nancy you can access it via the dot notation. Or via the class indexer.
var name = parameters.name;
var name = parameters["name"];
This is handy when you're sending query string or form names that have values that cannot be used in dot notation.
var firstName = parameters["first-name"];
The values are also dynamic, so it could be made up of nested objects. This allows you to do stuff like:
var firstName = parameters.contact.firstname;
So if you're passing a JSON payload to the request then you can access the entire structure using dot notation.
However you will probably find most developers using Nancy only ever access Route values or QueryString values using this method.
Get["/products/{id:int}/"] = parameters => {
int id = parameters.id;
};
So back to the original question:
Is there a blog post or any doco: Nope.
Why does it exist: For sugar syntax.
Can I use it for what I want: Yes absolutely!
Can you tell me how to use it: Nope, however it shouldn't be hard. Just look the model binding in Nancy to figure it out. It's not too hard.
Just an edit based on the answer by the OP.
When you access the dot notation, continued dot notation will only work on further dynamic types.
This means using var will cause an exception because of the way var and dynamic are handled by the compiler.
When you do:
var person = parameters.person;
var name = person.name;
parameters is currently dynamic and implements TryGetMember, this internally looks up a dictionary of values and attempts to return the value.
When you define the object as var for the person variable. The compiler assumes that anything after that exists on the object, so it looks for name on the person variable.
Since name does not exist as a member of person it will throw.
To resolve this, the variable must be assigned as dynamic. So the example becomes:
dynamic person = parameters.person;
var name = person.name;
This will work.
So I started working with the DynamicDictionary and it is pretty cool and easy to work with. Only one thing bugs me right now. That is if I nest DynamicDictionaries.
Look at the following example:
private void TestNestedDynamicDictionary()
{
dynamic dictionary = new DynamicDictionary();
dynamic nestedDictionary = new DynamicDictionary();
nestedDictionary.Add("name", "Peter");
dictionary.Add("person", nestedDictionary);
var person = dictionary.person;
var name = person.name;
Console.WriteLine(name);
}
This fails when trying to access person.name with a 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
DynamicDictionaryValue' does not contain a definition for 'name'
If I just do an explicit cast like this it works.
var person = (DynamicDictionary)dictionary.person;
Any input on how I could make it behave as DynamicDictionary right out of the box... apart from checking the DynamicDictionaryValue before it is returned, and do the cast there, which I think is messy.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (!dictionary.TryGetValue(binder.Name, out value))
{
result = new DynamicDictionaryValue(null);
return true;
}
var dictVal = value as DynamicDictionaryValue;
if (null != dictVal && dictVal.Value is DynamicDictionary)
{
result = dictVal.Value;
}
else
{
result = value;
}
return true;
}
Is there anyway I can get the name of class property IntProperty?
public class ClassName
{
public static int IntProperty { get { return 0; } }
}
//something like below but I want to get the string of "IntProperty"
ClassName.IntProperty.GetType().Name
Basically what I want to do is to dynamically save property name string into the database, and later on retrieve it from the database and invoke the property dynamically.
Seems like what I am looking for is similar to duck typing I think.
Thanks!
UPDATED:
This is the actual code. This is more like a workflow kind of thing. But each task is defined as property of a class (class is used to group tasks).
public class ApplicationTask
{
public static Task<string> SendIncompleteNotification
{
get
{
return new Task<string>
(
a => Console.WriteLine("Sample Task")
, "This is a sample task which does nothing."
);
}
}
}
So, the code will be able to retrieve the full name of the class and property something like: namespace.ApplicationTask.SendIncompleteNotification and save this into the database. Later on, the code will read the string and dynamically create the task and pass it into another to execute.
With C#6.0 you can get it by
nameof(ClassName.IntProperty)
I think that the use of the GetProperty method in this case, is redundant, because you need to know the property name to call the method.
You could loop through your properties and extract its name:
foreach (PropertyInfo p in typeof(ClassName).GetProperties())
{
string propertyName = p.Name;
//....
}
The result of ClassName.IntProperty is just an integer value. As soon as it's executed and the result is returned, there's no trace of it having come from IntProperty.
If you're using .NET 3.5 you can use an expression tree instead, usually created via a lambda expression:
Expression<Func<int>> exp = () => ClassName.IntProperty;
You can then compile and execute the expression and separately find out what it's doing (retrieving IntProperty in this case). I'm not really sure whether this is suitable for what you want to do though.
If you do work out how to save the property name in the database, then GetProperty is the way to go on the retrieval front.
Perhaps if you could give more context in the question in terms of how you want to use this, we could help more. You've shown just an expression - if you could show it in terms of where you'd be using it, that would be great.
EDIT: You've expanded the property, but not how it's being called. Do you need to call it directly, rather than just fetching the list of properties using Type.GetProperties and storing the list of property names in the database?
Again, if you could show the code which calls the property, and how you want it to interact with the database, we may be able to make more progress.
Type objectType = this.GetType();
PropertyInfo property = objectType.GetProperty("intProperty");
System.Console.Write(property.Name);
Is this what you need?
You can simply use nameof(ClassName.IntProperty)
It will give you "IntProperty"
I came across this, and it seems very helpful for getting property name. (C++)
#define getVarName(varName,holder) sprintf(holder, "%s", #varName)
int main() {
int var = 100; // just any type of identifier
char name[100]; // it will get the variables name
getVarName(var, name);
puts(name);
return 0;
}
ref: http://zobayer.blogspot.com/2010/05/c-fun-get-variables-name.html