Get class name of enum by its value - c#

I have some enum
public enum MyEnum
{
Field1,
Field2
}
and pass value in function
DoSmth(MyEnum.Field1);
How can i get classname "MyEnum" in that function
void DoSmth(Enum enumArg)
{
string className = Magic(enumArg); // className = "MyEnum"
}

Note that the code you've posted doesn't compile. enum is a reserved word and cannot be used as a variable name. The following will work, however.
void DoSmth(Enum e)
{
string className = e.GetType().Name; // className = "MyEnum"
}

If you just need to check if enum is MуEnum then it's better to check as if (enum is MyEnum)
If you need type name then you need enum.GetType().Name

Related

how to get varriable name over another one c#?

string MyVar1 = "bilah bilah";
dosometing(MyVar1);
void dosometing(object MyObject)
{
string VarName = nameof(MyObject); // it givess : "MyObject"
}
But I was expecting "MyVar1" is there a way for that? using dynamic? or ref?
That's not possible. But you can do something like:
string MyVar1 = "bilah bilah";
dosometing(MyVar1, nameof(MyVar1));
void dosometing(string MyString, string VarName)
{
// MyString holds the value
// VarName holds the variable name
}
Maybe this information is usefull for you.
Since you want the value and the name of the property that has changed you could move the method dosomething inside the setter of the property.
(Notice: I am assuming you are actually working with properties and not local variables as shown in your question, and your question is just simplified)
So something like this:
public class Foo
{
private string _myVar1;
public string MyVar1
{
get => _myVar1;
set
{
_myVar1 = value;
DoSomething(value);
}
}
private void DoSomething(string value, [CallerMemberName]string propertyName = "")
{
Console.WriteLine(value);
Console.WriteLine(propertyName);
}
}
The attribute CallerMemberName requires the using System.Runtime.CompilerServices
More Information can be found here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute
See it in action here: https://dotnetfiddle.net/YvqqdP

Get full name of parameter (namespace, class, method and name) c#

How would I get the namespace, class, method and name of a parameter or variable. For example:
namespace TheNamespace
{
class Theclass
{
void Thing()
{
string thevariable = "";
string b = thevariable.GetFullName();
// b would be equal to TheNamespace.Theclass.Thing.thevariable
}
}
}
How would I do this
Parameters and variables don't have namespace/class name so to get string you are looking for you simply combine Can you use reflection to find the name of the currently executing method? and get name of a variable or parameter:
string b =
System.Reflection.MethodBase.GetCurrentMethod().Name + "." +
nameof(thevariable);

Can I change this extension method to remove the "magic string"? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding the Variable Name passed to a Function in C#
The class below contains the field city.
I need to dynamically determine the field's name as it is typed in the class declaration
i.e. I need to get the string "city" from an instance of the object city.
I have tried to do this by examining its Type in DoSomething() but can't find it when examining the contents of the Type in the debugger.
Is it possible?
public class Person
{
public string city = "New York";
public Person()
{
}
public void DoSomething()
{
Type t = city.GetType();
string field_name = t.SomeUnkownFunction();
//would return the string "city" if it existed!
}
}
Some people in their answers below have asked me why I want to do this.
Here's why.
In my real world situation, there is a custom attribute above city.
[MyCustomAttribute("param1", "param2", etc)]
public string city = "New York";
I need this attribute in other code.
To get the attribute, I use reflection.
And in the reflection code I need to type the string "city"
MyCustomAttribute attr;
Type t = typeof(Person);
foreach (FieldInfo field in t.GetFields())
{
if (field.Name == "city")
{
//do stuff when we find the field that has the attribute we need
}
}
Now this isn't type safe.
If I changed the variable "city" to "workCity" in my field declaration in Person this line would fail unless I knew to update the string
if (field.Name == "workCity")
//I have to make this change in another file for this to still work, yuk!
{
}
So I am trying to find some way to pass the string to this code without physically typing it.
Yes, I could declare it as a string constant in Person (or something like that) but that would still be typing it twice.
Phew! That was tough to explain!!
Thanks
Thanks to all who answered this * a lot*. It sent me on a new path to better understand lambda expressions. And it created a new question.
Maybe you need this. Works fine.
I found this here.
static void Main(string[] args)
{
var domain = "matrix";
Check(() => domain);
Console.ReadLine();
}
static void Check<T>(Expression<Func<T>> expr)
{
var body = ((MemberExpression)expr.Body);
Console.WriteLine("Name is: {0}", body.Member.Name);
Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member)
.GetValue(((ConstantExpression)body.Expression).Value));
}
Output will be:
Name is: 'domain'
Value is: 'matrix'
I know this is old question, but I was trying to achieve the same and google sent me here. After many hours I finally found a way. I hope somebody else will find this useful.
There are actually more ways to accomplish this:
static void Main(string[] args)
{
GetName(new { var1 });
GetName2(() => var1);
GetName3(() => var1);
}
static string GetName<T>(T item) where T : class
{
return typeof(T).GetProperties()[0].Name;
}
static string GetName2<T>(Expression<Func<T>> expr)
{
return ((MemberExpression)expr.Body).Member.Name;
}
static string GetName3<T>(Func<T> expr)
{
return expr.Target.GetType().Module.ResolveField(BitConverter.ToInt32(expr.Method.GetMethodBody().GetILAsByteArray(), 2)).Name;
}
The first is fastest. The last 2 are approx 20 times slower than the 1st one.
http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
city in this case is an instance of type string. When you call .GetType() you return the actual string type, which has no knowledge at all of your particular city instance.
I'm having a hard time seeing why you can't just type "city" in the code as a string literal here, if that's what you need. Perhaps it would help if you shared what you want to use this value for and in what circumstances you will call your DoSomething() function.
At the moment, my best guess is that what you really want to do is reflect the entire Person class to get a list of the fields in that class:
public void DoSomething()
{
MemberInfo[] members = this.GetType().GetMembers();
// now you can do whatever you want with each of the members,
// including checking their .Name properties.
}
Okay, based on your edit I have some more for you.
You can find the name of fields that are decorated with your attribute at run-time like this:
Type t = typeof(Person);
foreach (MemberInfo member in t.GetMembers()
.Where(m =>
m.GetCustomAttributes(typeof(MyCustomAttribute)).Any() ) )
{
// "member" is a MemberInfo object for a Peson member that is
// decorated with your attribute
}
You can also use binding flags in the first GetMembers() call to limit it to just fields, if you want.
You mentioned "i.e. I need to get the string "city" from an instance of the object city."
Are you looking to get the field name from the value of the field.
For example:If there are 2 Person object one with city "New York" and the other with city "London", are you looking for the function to return "city". Is this what you mean by dynamic?
With your current design you will always need to compare the name of the field from the FieldInfo against a string.
What if you instead decouple this so that you hold the identifier to use for comparison purposes during reflection as part of the attribute.
Something like this:
public enum ReflectionFields
{
CITY = 0,
STATE,
ZIP,
COUNTRY
}
[AttributeUsage(AttributeTargets.Field,AllowMultiple=false)]
public class CustomFieldAttr : Attribute
{
public ReflectionFields Field { get; private set; }
public string MiscInfo { get; private set; }
public CustomFieldAttr(ReflectionFields field, string miscInfo)
{
Field = field;
MiscInfo = miscInfo;
}
}
public class Person
{
[CustomFieldAttr(ReflectionFields.CITY, "This is the primary city")]
public string _city = "New York";
public Person()
{
}
public Person(string city)
{
_city = city;
}
}
public static class AttributeReader<T> where T:class
{
public static void Read(T t)
{
//get all fields which have the "CustomFieldAttribute applied to it"
var fields = t.GetType().GetFields().Where(f => f.GetCustomAttributes(typeof(CustomFieldAttr), true).Length == 1);
foreach (var field in fields)
{
var attr = field.GetCustomAttributes(typeof(CustomFieldAttr), true).First() as CustomFieldAttr;
if (attr.Field == ReflectionFields.CITY)
{
//You have the field and you know its the City,do whatever processing you need.
Console.WriteLine(field.Name);
}
}
}
}
public class Program
{
public static void Main(string[] args)
{
PPerson p1 = new PPerson("NewYork");
PPerson p2 = new PPerson("London");
AttributeReader<PPerson>.Read(p1);
AttributeReader<PPerson>.Read(p2);
}
}
You can now freely rename _city field of Person to something else and your calling code will still work since the code using reflection is trying to identify the field using the ReflectionFields enum value set as part of initialization of the attribute set on the field.
Yes its possible !!!
Try this out...
public string DoSomething(object city)
{
return city.GetType().GetProperty("Name",typeof(string)).GetValue(city,null);
}
Two things here.
Number one, as someone above pointed out, you're getting the Type for string, not for Person. So typeof(Person).GetMembers() will get you the list of members.
Number two, and more importantly, it looks like you're misunderstanding the purpose of attributes. In general attributes are used to mark a member for specific processing or to add additional information. Here you're using the name to indicate what processing you want, and the attribute to specify parameters, which is mixing of metaphors, or something.
Abhijeet's answer is more appropriate, you mark the field as a city field, then do what you like with it. Where I disagree is that I would use different attribute classes, rather than an enumeration.
Something like:
public class MyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field)]
public class MyCityAttribute : MyAttribute
{
}
[AttributeUsage(AttributeTargets.Field]
public class MyNameAttribute: MyAttribute
{
}
public class Person
{
[MyCity]
public string city = "New York";
[MyCity]
public string workCity = "Chicago";
[MyName]
public string fullName = "John Doe";
public Person()
{
}
public void DoSomething()
{
Type t = typeof(Person);
FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var field in fields)
{
MyAttribute[] attributes = field.GetCustomAttributes(typeof(MyAttribute));
if (attributes.Count > 0)
{
if (attributes[0] is MyCityAttribute)
{
//Dosomething for city
break;
}
if (attributes[0] is MyNameAttribute)
{
//Dosomething for names
break;
}
}
}
}
}
This would allow you to use different parameters for MyCity vs MyName that would make more sense in the context of processing each.
I think with your 'yuk' comment above, you hit the nail on the head. That you would have to change a string constant if you rename your variable is an indicator that you're doing something wrong.
t.GetField("city", BindingFlags.Public | BindingFlags.Instance);
or you can call GetFields() to get all fields
You need to call get type on the class Person. The iterate the fields of the class as in the answer below
This is not possible (I think it actually is but involes several hacks and using lambdas). If you want to store attributes about a Person and be able to get the name of the attribute easily, I suggest using a Dictionary<TKey, TValue> from the System.Collections.Generic namespace.
And you can always make public properties that wrap the dictionary.
public class Person
{
Dictionary<string, string> attributes = new Dictionary<string, string();
public string City
{
get { return attributes["city"]; }
set { attributes["city"] = value; }
}
public Person()
{
City = "New York";
}
}
And you can get a list of all attributes with attributes.Keys.
Have a look at this post as it looks similar to what you're trying to do:
Finding the variable name passed to a function
(especially Konrad Rudolph's answer) Another approach could be to just add "city" as one of the parameters in the attribute and fish that out later.
You are already looping through the collection of FieldInfo objects. Look for your attribute on those and when you find the FieldInfo that contains your attribute, you have the one you want. Then call .Name on it.
system.reflection.fieldinfo.attributes

Get the original property name from a method parameter

How can I get the name of the original property name which is passed as a parameter to a method?
class TestA
{
public string Foo { get; set; }
public TestA()
{
Foo = "Bar";
TestB.RegisterString(Foo);
}
}
class TestB
{
public static void RegisterString(string inputString)
{
// Here I want to receive the property name that was used
// to assign the parameter input string
// I want to get the property name "Foo"
}
}
You can add an argument with the nameof keyword. Not sure why you would want that anyway:
TestB.RegisterString(Foo, nameof(Foo));
This will pass in "Foo" as the second argument. There is no way to automate this, so you don't need to call nameof yourself, which makes doing this quite useless.
If you would call this from the Foo property, you could use the CallerMemberNameAttribute, which will put in the caller's name. The compiler will set the correct value, so you don't have to supply this yourself in the calling method.
public static void RegisterString( string inputString
, [CallerMemberName] string caller = null
)
{
// use caller here
}
That makes more sense to me.

set Enums using reflection

How to set Enums using reflection,
my class have enum :
public enum LevelEnum
{
NONE,
CRF,
SRS,
HLD,
CDD,
CRS
};
and in runtime I want to set that enum to CDD for ex.
How can I do it ?
Try use of class Enum
LevelEnum s = (LevelEnum)Enum.Parse(typeof(LevelEnum), "CDD");
public class MyObject
{
public LevelEnum MyValue {get;set,};
}
var obj = new MyObject();
obj.GetType().GetProperty("MyValue").SetValue(LevelEnum.CDD, null);
value = (LevelEnum)Enum.Parse(typeof(LevelEnum),"CDD");
So basically you just parse the string corresponding to the enum value that you wish to assign to the variable. This will blow if the string is not a defined member of the enum. you can check that with Enum.IsDefined(typeof(LevelEnum),input);

Categories