i want to create an instance of object with a dynamic parameter like
private Type ClassType { get; set; }
model = (CreateObject<typeof(this.ClassType)>)ser.Deserialize(sr);
private T CreateObject<T>()
{
return (T)Activator.CreateInstance(this.ClassType);
}
i want to try it without a fix Type like "startconfig".
but it still doesnt work, can u help me?
var mi = GetType().GetMethod("CreateObject");
var miConstructed = mi.MakeGenericMethod(this.ClassType);
var instance = miConstructed.Invoke(this, null);
var model = (instance)ser.Deserialize(sr);
}
private T CreateObject<T>()
{
return (T)Activator.CreateInstance(this.ClassType);
}
this doesnt work anyway, cause: he type or namespace name 'type/namespace' could not be found (are you missing a using directive or an assembly reference?)
that happends at casting the ser.Deserialize(sr);
You wanna create an instance of T ? Then :
var model = CreateObject<StartConfig>();
private T CreateObject<T>()
{
return (T)Activator.CreateInstance(typeof(T));
}
with your second code sample, you might do something like that.
private Type ClassType { get; set; }
var mi = GetType().GetMethod("CreateObject");
var miConstructed = mi.MakeGenericMethod(ClassType);
var instance = miConstructed.Invoke(this, null);
model = (instance)ser.Deserialize(sr);
private T CreateObject<T>()
{
return (T)Activator.CreateInstance(typeof(T));
}
Try...
public class Factory<T>
{
public static T getInstance()
{
return getInstance(typeof(T), null);
}
public static T getInstance(object[] initializationParameters)
{
return (T)Activator.CreateInstance(typeof(T), initializationParameters);
}
{
What do you want to do with your model? I mean interface-wise. You have to define an interface which all Types adhere to that you deserialize.
public interface IModel
{
int ComputeFavoriteNumber(); // or a property
}
...
// class is practically unknown to deserializing module
internal class ErnieModel : IModel
{
public int ComputeFavoriteNumber()
{
return 8243721;
}
}
...
// deserializing module
var bf = new BinaryFormatter();
using (var ms = new MemoryStream())
{
bf.Serialize(ms, new ErnieModel()); // In reality ErnieModel should be unknown to the deserializing code, this is just to fill the Stream with data
ms.Position = 0;
var model = (IModel)bf.Deserialize(sr);
Console.WriteLine("Favorite number: {0}", model.ComputeFavoriteNumber());
}
You don't even need Activator.CreateInstance in this case. You do need it however, if you just saved the fully qualified name of the type or the type itself (not sure if that works) you want to create.
// interfaces/classes the same as above
Type deserializedType = typeof(ErnieModel); // or get it from wherever, maybe through (Type)bf.Deserialize(stream); ? In reality ErnieModel should be unknown to the deserializing code
var model = (IModel)Activator.CreateInstance(deserializedType);
Console.WriteLine("Favorite number: {0}", model.ComputeFavoriteNumber());
Using generics doesn't make sense in this case (though it feels like a good place to apply at first), you have to go with oldschool object and casting to a known interface type to enable true plugin-like extensions.
Related
I have a .NET class which represents a RPC method call, like this:
class MethodCall
{
public string MethodName { get; set; }
public Collection<object> Arguments { get; set; }
}
I want to serialize a Collection<MethodCall> to YAML. I'm using YamlDotNet to achieve this.
By default, YamlDotNet will serialize these objects like this:
methodName: someName
arguments:
- arg1
- arg2
- ...
I would like to simplify the resulting YAML to:
someName:
- arg1
- arg2
Is there any easy way to achieve this? Please note that the arguments can be complex objects (i.e. not simple scalars).
You can achieve this by registering an implementation of IYamlTypeConverter that performs the conversion that you need.
Here's a possible implementation:
public sealed class MethodCallConverter : IYamlTypeConverter
{
// Unfortunately the API does not provide those in the ReadYaml and WriteYaml
// methods, so we are forced to set them after creation.
public IValueSerializer ValueSerializer { get; set; }
public IValueDeserializer ValueDeserializer { get; set; }
public bool Accepts(Type type) => type == typeof(MethodCall);
public object ReadYaml(IParser parser, Type type)
{
parser.Consume<MappingStart>();
var call = new MethodCall
{
MethodName = (string)ValueDeserializer.DeserializeValue(parser, typeof(string), new SerializerState(), ValueDeserializer),
Arguments = (Collection<object>)ValueDeserializer.DeserializeValue(parser, typeof(Collection<object>), new SerializerState(), ValueDeserializer),
};
parser.Consume<MappingEnd>();
return call;
}
public void WriteYaml(IEmitter emitter, object value, Type type)
{
emitter.Emit(new MappingStart());
var call = (MethodCall)value;
ValueSerializer.SerializeValue(emitter, call.MethodName, typeof(string));
ValueSerializer.SerializeValue(emitter, call.Arguments, typeof(Collection<object>));
emitter.Emit(new MappingEnd());
}
}
The converter needs to be registered into the SerializerBuilder and DeserializerBuilder through the WithTypeConverter method. Note that YamlDotNet does not provide us with a way to call the (de)serializer recursively, so we have to set some public properties as a workaround. This is not as clean as it could be, but still works:
string SerializeMethodCall(MethodCall call)
{
var methodCallConverter = new MethodCallConverter();
var serializerBuilder = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.WithTypeConverter(methodCallConverter);
methodCallConverter.ValueSerializer = serializerBuilder.BuildValueSerializer();
var serializer = serializerBuilder.Build();
var yaml = serializer.Serialize(call);
return yaml;
}
MethodCall DeserializeMethodCall(string yaml)
{
var methodCallConverter = new MethodCallConverter();
var deserializerBuilder = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.WithTypeConverter(methodCallConverter);
methodCallConverter.ValueDeserializer = deserializerBuilder.BuildValueDeserializer();
var deserializer = deserializerBuilder.Build();
var call = deserializer.Deserialize<MethodCall>(yaml);
return call;
}
I'm trying to put a series of functions together for Entity Framework use. The idea is that I want to pass generic classes all into one routine, and then have the routine "type" it for me and act accordingly. I can't seem to figure out how to marry the Class back up with it's PropertyType.
public void AddUpdate(string classType, Object o)
{
//This gets the Type of my Class Object ok.
Type mType = Type.GetType(GetType().Namespace + "." + classType, true);
var meContext = new ClsContext(_ConnectionString);
//This retrieves the correct primary key for my the Class Object.
string key = FncGetPrimaryKey(meContext, classType + "s");
//I've tried this as a PropertyInfo as well instead of a Var
var keyID = o.GetType().GetProperty(key);
//I've tried this as Var as well as Dynamic
dynamic obj = o;
//Now I'm stuck, because I want to evaluate the property,
//but I get an error "<MyClass> does not contain a reference for 'keyID'
if (obj.keyID == 0) //ERROR ON THIS LINE
{
meContext.Entry(o).State = EntityState.Added;
}
else
{
meContext.Entry(o).State = EntityState.Modified;
}
meContext.SaveChanges();
}
Although, I did not fully understand why do you want it like this, I think, I understood what you are trying to achieve. This is how I do it in case if I want to add some common object:
public void AddUpdate<T>(T obj) where T : IEntity
{
using(var ctx = new ClsContext(_ConnectionString))
{
if (obj.keyID == 0)
{
ctx.Entry(o).State = EntityState.Added;
}
else
{
ctx.Entry(o).State = EntityState.Modified;
}
ctx.SaveChanges();
}
}
public interface IEntity
{
int keyId {get;set;}
}
Try:
var keyValue = keyID.GetValue(o);
if (keyValue.Equals(0)) {...
I have a (string, object) dictionary, object (class) has some values including data type which is defined by enum. I need a GetItemValue method that should return dictionary item's value. So return type must be the type which is defined in item object.
Class Item
{
String Name;
DataValueType DataType;
Object DataValue;
}
private Dictionary<string, Item> ItemList = new Dictionary<string, Item>();
void Main()
{
int value;
ItemList.Add("IntItem", new Item("IntItem", DataValueType.TInt, 123));
value = GetItemValue("IntItem"); // value = 123
}
What kind of solution can overcome this problem?
Best Regards,
You can use Generic Classes
Class Item<T>
{
String Name;
T DataTypeObject;
Object DataValue;
public T GetItemValue()
{
//Your code
return DataTypeObject;
}
}
A better solution would be to introduce an interface that you make all the classes implement. Note that the interface doesn't necessarily have to specify any behavior:
public interface ICanBePutInTheSpecialDictionary {
}
public class ItemTypeA : ICanBePutInTheSpecialDictionary {
// code for the first type
}
public class ItemTypeB : ICanBePutInTheSpecialDictionary {
// code for the second type
}
// etc for all the types you want to put in the dictionary
To put stuff in the dictionary:
var dict = new Dictionary<string, ICanBePutInTheSpecialDictionary>();
dict.add("typeA", new ItemTypeA());
dict.add("typeB", new ItemTypeB());
When you need to cast the objects to their specific types, you can either use an if-elseif-block, something like
var obj = dict["typeA"];
if (obj is ItemTypeA) {
var a = obj as ItemTypeA;
// Do stuff with an ItemTypeA.
// You probably want to call a separate method for this.
} elseif (obj is ItemTypeB) {
// do stuff with an ItemTypeB
}
or use reflection. Depending on how many choices you have, either might be preferrable.
If you have a 'mixed bag' you could do something like this...
class Item<T>
{
public String Name { get; set; }
public DataValueType DataType { get; set; }
public T DataValue { get; set; }
}
class ItemRepository
{
private Dictionary<string, object> ItemList = new Dictionary<string, object>();
public void Add<T>(Item<T> item) { ItemList[item.Name] = item; }
public T GetItemValue<T>(string key)
{
var item = ItemList[key] as Item<T>;
return item != null ? item.DataValue : default(T);
}
}
and use it like...
var repository = new ItemRepository();
int value;
repository.Add(new Item<int> { Name = "IntItem", DataType = DataValueType.TInt, DataValue = 123 });
value = repository.GetItemValue<int>("IntItem");
If you have just a couple types - you're better off with Repository<T>.
I found a solution exactly what I want. Thanks to uncle Google.
Thanks all of you for your kind interest.
public dynamic GetValue(string name)
{
if (OpcDataList[name].IsChanged)
{
OpcReflectItem tmpItem = OpcDataList[name];
tmpItem.IsChanged = false;
OpcDataList[name] = tmpItem;
}
return Convert.ChangeType(OpcDataList[name].ItemValue.Value, OpcDataList[name].DataType);
}
I have a Types project where I define custom class objects that I want to work on in my main application. The objects are basically derived from strings and parsed into a structure.
I have two problems
1 - In a separate project I have a File reader class where I scan text files for the string types I have defined. For example by regular expression. Currently I added my Types project as a project reference and I just list the regular expressions at the top of my read class. When i find a type I convert the string to the appropriate type. However how can i improve this so that is it directly connected to my Types project - so when i update it with new types the Read class knows that it should support the new types?
2 - I'm trying to create a DLL that works on these specific types after they are read from the text file. How do I tell my DLL that I want to support the types in my Types project? Do I have to make an overloaded function for each type I want to work on? Do I use an interface?
Any advice is greatly appreciated.
EDIT: Added example code of what I''m trying to do
//PROJECT 1 - handles IO operation like Reading and writing
//function in read class job is to find one of several predefined string types by regular expression...once found they are converted to the data structure (by passing string to constructor of type class defined in the other project
public class Read
{
public string[] FileList { get; set; }
private static Int64 endOffset = 0;
private FileStream readStream;
private StreamReader sr;
private System.Text.RegularExpressions.Regex type1 = new System.Text.RegularExpressions.Regex(#"#123:test");
private System.Text.RegularExpressions.Regex type2 = new System.Text.RegularExpressions.Regex(#"TESTTYPE2");
public Read(string[] fl)
{
FileList = fl;
}
public object ReturnMessage(FileStream readStream, out int x)
{
//readStream = new FileStream(file, FileMode.Open, FileAccess.Read);
x = 0;
//endOffset = 0;
bool found = false;
char ch;
string line = string.Empty;
object message = null;
while (!(x < 0)) //do this while not end of line (x = -1)
{
readStream.Position = endOffset;
//line reader
while (found == false) //keep reading characters until end of line found
{
x = readStream.ReadByte();
if (x < 0)
{
found = true;
break;
}
// else if ((x == 10) || (x == 13))
if ((x == 10) || (x == 13))
{
ch = System.Convert.ToChar(x);
line = line + ch;
x = readStream.ReadByte();
if ((x == 10) || (x == 13))
{
ch = System.Convert.ToChar(x);
line = line + ch;
found = true;
}
else
{
if (x != 10 && (x != 13))
{
readStream.Position--;
}
found = true;
}
}
else
{
ch = System.Convert.ToChar(x);
line = line + ch;
}
}//while - end line reader
//examine line (is it one of the supported types?)
if (type1.IsMatch(line))
{
message = line;
endOffset = readStream.Position;
break;
}
else
{
endOffset = readStream.Position;
found = false;
line = string.Empty;
}
}//while not end of line
return message;
}
}
//PROJECT 2 - contains classes that define the types
//TYPE1
namespace MessageTypes.Type1
{
public sealed class Type1
{
public List<Part> S2 { get; set; }
public Type1(string s)
{
S2 = new List<Part>();
string[] parts = s.Split(':');
for (int i = 0; i < parts.Length; i++)
{
S2.Add(new Part(parts[i]));
}
}
}
public sealed class Part
{
public string P { get; set; }
public Part(string s)
{
P = s;
}
}
}
//TYPE 2
namespace MessageTypes.Type2
{
public sealed class FullString
{
public string FS { get; set; }
public FullString(string s)
{
FS = s;
}
}
}
//PROJECT 3
class DoSomethingToTypeObject{
//detect type and call appropriate function to process
}
//PROJECT 4 -- MAIN PROJECT with GUI
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (tabControl1.SelectedIndex == 0) //Processing Mode 1
{
//load file list from main window - Mode1 tab
IOHandler.Read read = new IOHandler.Read(new string[2] { #"C:\file1.txt", #"C:\file2.txt" });
//read files
foreach (string file in read.FileList)
{
//while not end of stream
myobject = read.ProcessFile(file);
DoSomethingtoTypeObject DS = new DoSomethingtoTypeObject(myobject);
//write transoformed object
write(myobject);
}
}
}
}
You should use an interface, then make all of your types implement the interface. After doing that, you should then change your Read class to operate on the interface NOT the individual classes.
That way you can add as many types as you want and not have to update the Read class.
I hope I understand you correctly.
The class you create in the Type project represent some objects that have different behaviors but the same data members and you would like to be able to use these easily within your projects without the hassle of having to explicitly list these objects.
I would create some base interface that all my objects in the Types project would implement.
I would then use a Factory Class that would use reflection to collect all objects that implement said interface.
public interface iFoo
{
string FoundItem { get; set; }
string Expression { get; }
string Value { get; set; }
void sharedFunctionName();
}
public static class FooFactory
{
public static List<iFoo> GetTypeList()
{
List<iFoo> types = new List<iFoo>();
types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from t in assembly.GetTypes()
where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))
select Activator.CreateInstance(t) as iFoo);
return types;
}
}
Then your Reader would receive all necessary information for the supported types without you having to manually dictate it anymore.
Since I guess the value type would be different at some point, you could use a Generic Interface like this :
public interface iFoo
{
string FoundItem { get; set; }
string Expression { get; }
void sharedFunctionName();
}
public interface iFoo<T> : iFoo
{
T Value { get; set; }
}
public static class FooFactory
{
public static List<iFoo> GetTypeList()
{
List<iFoo> types = new List<iFoo>();
types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from t in assembly.GetTypes()
where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))
select Activator.CreateInstance(t) as iFoo);
return types;
}
}
public class FooBar : iFoo<int>
{
}
In this example the base interface iFoo is kept to ease the discovery process.
Using generic interface would allow to kept your code Type safe (as opposed to using a Value of type object) but you will have to add some logic when recovering your objects to be able to access your Value properly.
Plus, if you ever need to create functions that would require to be shared within all your objects you would be able to add extension methods within the Factory Class and VoilĂ .
EDIT:
Based on the new information:
Your Types correspond to a type of data that you will find in a file based on some regular expression.
There might be different type of transformation based on the user selection and the Type.
We know that the user will have to pick a mode from a list and this will affect the transformation to apply on the Types.
So this is what I would do :
I would move the transformation logic right into the Type class, polymophism will take care of exactly which transformation will be called.
I would put the RegularExpression to use to detect the Type into the Type itself, this will allow you to use reflection and the Factory class discuss earlier more easily.
This way, everything is standard. Your reader is aware of any new type you create in the type project without manual intervention and once detected the right transformation could be applied and the original string is always accessible.
public enum UserMode {Mode1, Mode2};
public interface iType
{
string Expression {get;}
string OriginalString {get; set;}
string Transform(UserMode Mode);
iType getNewInstance(string OriginalString);
}
public class Type1 : iType
{
public string Expression {get { return "RegularExpression"; }}
public string OriginalString {get; set;}
//Add any other private members you need to accomplish your work here.
public string Transform(UserMode Mode)
{
switch(Mode)
{
case UserMode.Mode1:
//write the transformation code for this scenario
return ResultString;
break;
}
}
public iType getNewInstance(string Original)
{
return (iType)(new Type1(){ OriginalString = Original });
}
}
public static class TypeFactory
{
public static List<iType> GetTypeList()
{
List<iType> types = new List<iType>();
types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from t in assembly.GetTypes()
where t.IsClass && t.GetInterfaces().Contains(typeof(iType))
select Activator.CreateInstance(t) as iType);
return types;
}
}
Now, all you will have to do if match the expression from the iTypes in the list.
When you have a match you do :
var TransformationReady = from t in TypeFactory.GetTypeList()
where Regex.IsMatch(YourFileLine, t.Expression)
select t.getNewInstance(Regex.Match(YourFileLine, t.Expression));
I would like to get property name when I'm in it via reflection. Is it possible?
I have code like this:
public CarType Car
{
get { return (Wheel) this["Wheel"];}
set { this["Wheel"] = value; }
}
And because I need more properties like this I would like to do something like this:
public CarType Car
{
get { return (Wheel) this[GetThisPropertyName()];}
set { this[GetThisPropertyName()] = value; }
}
Since properties are really just methods you can do this and clean up the get_ returned:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var x = p.Something;
Console.ReadLine();
}
public string Something
{
get
{
return MethodBase.GetCurrentMethod().Name;
}
}
}
If you profile the performance you should find MethodBase.GetCurrentMethod() is miles faster than StackFrame. In .NET 1.1 you will also have issues with StackFrame in release mode (from memory I think I found it was 3x faster).
That said I'm sure the performance issue won't cause too much of a problem- though an interesting discussion on StackFrame slowness can be found here.
I guess another option if you were concerned about performance would be to create a Visual Studio Intellisense Code Snippet that creates the property for you and also creates a string that corresponds to the property name.
Slightly confusing example you presented, unless I just don't get it.
From C# 6.0 you can use the nameof operator.
public CarType MyProperty
{
get { return (CarType)this[nameof(MyProperty)]};
set { this[nameof(MyProperty)] = value]};
}
If you have a method that handles your getter/setter anyway, you can use the C# 4.5 CallerMemberName attribute, in this case you don't even need to repeat the name.
public CarType MyProperty
{
get { return Get<CarType>(); }
set { Set(value); }
}
public T Get<T>([CallerMemberName]string name = null)
{
return (T)this[name];
}
public void Set<T>(T value, [CallerMemberName]string name = null)
{
this[name] = value;
}
I'd like to know more about the context in which you need it since it seems to me that you should already know what property you are working with in the property accessor. If you must, though, you could probably use MethodBase.GetCurrentMethod().Name and remove anything after get_/set_.
Update:
Based on your changes, I would say that you should use inheritance rather than reflection. I don't know what data is in your dictionary, but it seems to me that you really want to have different Car classes, say Sedan, Roadster, Buggy, StationWagon, not keep the type in a local variable. Then you would have implementations of methods that do the proper thing for that type of Car. Instead of finding out what kind of car you have, then doing something, you then simply call the appropriate method and the Car object does the right thing based on what type it is.
public interface ICar
{
void Drive( decimal velocity, Orientation orientation );
void Shift( int gear );
...
}
public abstract class Car : ICar
{
public virtual void Drive( decimal velocity, Orientation orientation )
{
...some default implementation...
}
public abstract void Shift( int gear );
...
}
public class AutomaticTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
public class ManualTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
Use MethodBase.GetCurrentMethod() instead!
Reflection is used to do work with types that can't be done at compile time. Getting the name of the property accessor you're in can be decided at compile time so you probably shouldn't use reflection for it.
You get use the accessor method's name from the call stack using System.Diagnostics.StackTrace though.
string GetPropertyName()
{
StackTrace callStackTrace = new StackTrace();
StackFrame propertyFrame = callStackTrace.GetFrame(1); // 1: below GetPropertyName frame
string properyAccessorName = propertyFrame.GetMethod().Name;
return properyAccessorName.Replace("get_","").Replace("set_","");
}
FWIW I implemented a system like this:
[CrmAttribute("firstname")]
public string FirstName
{
get { return GetPropValue<string>(MethodBase.GetCurrentMethod().Name); }
set { SetPropValue(MethodBase.GetCurrentMethod().Name, value); }
}
// this is in a base class, skipped that bit for clairty
public T GetPropValue<T>(string propName)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
return GetAttributeValue<T>(attributeName);
}
public void SetPropValue(string propName, object value)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
SetAttributeValue(attributeName, value);
}
private static Dictionary<string, string> PropToAttributeMap = new Dictionary<string, string>();
private string GetCrmAttributeName(string propertyName)
{
// keyName for our propertyName to (static) CrmAttributeName cache
string keyName = this.GetType().Name + propertyName;
// have we already done this mapping?
if (!PropToAttributeMap.ContainsKey(keyName))
{
Type t = this.GetType();
PropertyInfo info = t.GetProperty(propertyName);
if (info == null)
{
throw new Exception("Cannot find a propety called " + propertyName);
}
object[] attrs = info.GetCustomAttributes(false);
foreach (object o in attrs)
{
CrmAttributeAttribute attr = o as CrmAttributeAttribute ;
if (attr != null)
{
// found it. Save the mapping for next time.
PropToAttributeMap[keyName] = attr.AttributeName;
return attr.AttributeName;
}
}
throw new Exception("Missing MemberOf attribute for " + info.Name + "." + propertyName + ". Could not auto-access value");
}
// return the existing mapping
string result = PropToAttributeMap[keyName];
return result;
}
There's also a custom attribute class called CrmAttributeAttribute.
I'd strongly recommend against using GetStackFrame() as part of your solution, my original version of the solution was originally the much neater:
return GetPropValue<string>();
But it was 600x slower than the version above.
Solution # 1
var a = nameof(SampleMethod); //a == SampleMethod
var b = nameof(SampleVariable); //b == SampleVariable
var c = nameof(SampleProperty); //c == SampleProperty
Solution # 2
MethodBase.GetCurrentMethod().Name; // Name of method in which you call the code
MethodBase.GetCurrentMethod().Name.Replace("set_", "").Replace("get_", ""); // current Property
Solution # 3
from StackTrace:
public static class Props
{
public static string CurrPropName =>
(new StackTrace()).GetFrame(1).GetMethod().Name.Replace("set_", "").Replace("get_", "");
public static string CurrMethodName =>
(new StackTrace()).GetFrame(1).GetMethod().Name;
}
you just need to call Props.CurrPropName or Props.CurrMethodName
Solution # 4
Solution for .NET 4.5+:
public static class Props
{
public static string GetCallerName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
return propertyName;
}
}
usage: Props.GetCallerName();
Yes, it is!
string test = "test string";
Type type = test.GetType();
PropertyInfo[] propInfos = type.GetProperties();
for (int i = 0; i < propInfos.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propInfos.GetValue(i);
string propName = pi.Name;
}
Try using System.Diagnostics.StackTrace to reflect on the call stack. The property should be somewhere in the call stack (probably at the top if you're calling it directly from the property's code).