Is there any way I can get the complete path of the property from the property itself ?
I have code design below as something:
class A
{
B BProperty { get; set; }
D DProperty { get; set; }
}
class B
{
D DProperty { get; set; }
}
class D
{
int Value { get; set; }
}
class Verification
{
public static void VerifyAProperty(A source, A dest)
{
VerifyBProperty(source.BProperty, dest.BProperty);
VerifyDProperty(source.DProperty, dest.DProperty);
}
public static void VerifyBProperty(B source, B dest)
{
VerifyDProperty(source.DProperty, dest.DProperty);
}
public static void VerifyDProperty(D source, D dest)
{
//// Here I want to verify source.value with dest.value and if they do not match I want to show an error message.
//// I have requirement to show the complete path of property that is under verification.
//// i.e either A->D->value or A->B->D->value
}
}
This is just a small part of my problem. I have number of similar verification to be done on number of different properties that can be at multiple places in the hierarchy.
I need to verify the source property with the destination property and in case if both do not match, show an error message that provides the path of the property that did not match.
I have tried something by passing a string property to VerifyProperty() function that will be appended as we go down the hierarchy. I just want to know if there is any better way to achieve this.
You can build an example where a property have multiple path:
var d = new D();
var b = new B { DProperty = d };
var a = new A { BProperty = b, DProperty = d };
In this example, the reference is the same in d, a.DProperty and a.BProperty.DProperty. It is the same reference stored at multiple places, hence it can't have an unique path.
That why there is no concept of (unique) property path in C#.
You have to add the path information by your own:
class Verification
{
public static void VerifyAProperty(A source, A dest, string path = null)
{
path += "->A";
VerifyBProperty(source.BProperty, dest.BProperty, path);
VerifyDProperty(source.DProperty, dest.DProperty, path);
}
public static void VerifyBProperty(B source, B dest, string path = null)
{
path += "->B";
VerifyDProperty(source.DProperty, dest.DProperty, path);
}
public static void VerifyDProperty(D source, D dest)
{
path += "->D";
if (source.Value != dest.Value)
Console.WriteLine($"Different values at: {path}");
}
}
An other option is reflection.
Related
Well, I would like to do my own benchmarking system like spark in Minecraft (https://github.com/lucko/spark):
I'm using Harmony lib (https://github.com/pardeike/Harmony) which allows me to interact/modify methods and allows me to add a Prefix/Postfix on each call that will help me out with this stack.
The basic structure has something similar to (https://github.com/pardeike/Harmony/issues/355):
[HarmonyPatch]
class MyPatches
{
static IEnumerable<MethodBase> TargetMethods()
{
return AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly())
.SelectMany(type => type.GetMethods())
.Where(method => method.ReturnType != typeof(void) && method.Name.StartsWith("Do"));
}
static void Prefix(out Stopwatch __state, MethodBase __originalMethod)
{
__state = Stopwatch.StartNew();
// ...
}
static void Postfix(Stopwatch __state, MethodBase __originalMethod)
{
__state.Stop();
// ....
}
}
The problem here is that the __originalMethod doesn't take care if it was called from A or B.
So for example, we had patched string.Join method. And the we call from A or B, where A or B, is the full callstack of this method.
So first, we need to assign a ID to this call, and we need to create a Tree-based structure (which is hard to serialize later), from here (https://stackoverflow.com/a/36649069/3286975):
public class TreeModel : Tree<TreeModel>
{
public int ID { get; set; }
public TreeModel() { }
public TreeModel(TreeModel parent) : base(parent) { }
}
public class Tree<T> where T : Tree<T>
{
protected Tree() : this(null) { }
protected Tree(T parent)
{
Parent=parent;
Children=new List<T>();
if(parent!=null)
{
parent.Children.Add(this as T);
}
}
public T Parent { get; set; }
public List<T> Children { get; set; }
public bool IsRoot { get { return Parent==null; } }
public T Root { get { return IsRoot?this as T:Parent.Root; } }
public T RecursiveFind(Predicate<T> check)
{
if(check(this as T)) return this as T;
foreach(var item in Children)
{
var result=item.RecursiveFind(check);
if(result!=null)
{
return result;
}
}
return null;
}
}
Now, the thing is that we need to fill the Tree as long as we iterate all the method and instructions got from Harmony. Forget about Harmony for a second, I will explain only two facts about it.
The lib allows you first to get all patched methods through IEnumerable<MethodBase> TargetMethods() so, you have the Assembly X passed through reflection and filtered all methods that are allowed to be patched (some of them broke Unity, so I decided to skip methods from UnityEngine., UnityEditor. and System.* namespaces).
And we have also the ReadMethodBody method (https://harmony.pardeike.net/api/HarmonyLib.PatchProcessor.html#HarmonyLib_PatchProcessor_ReadMethodBody_System_Reflection_MethodBase_) from a given MethodBase it returns all IL stack instructions.
So we can start to iterate over and over in order to get all instructions and fill the entire tree. This is what I wrote last night:
internal static class BenchmarkEnumerator
{
internal static Dictionary<MethodBase, int> Mappings { get; } = new Dictionary<MethodBase, int>();
internal static Dictionary<int, TreeModel> TreeIDs { get; } = new Dictionary<int, TreeModel>();
internal static Dictionary<MethodBase, BenchmarkTreeModel> TreeMappings { get; } = new Dictionary<MethodBase, BenchmarkTreeModel>();
private static HashSet<int> IDUsed { get; } = new HashSet<int>();
public static int GetID(this MethodBase method)
{
return GetID(method, out _);
}
public static int GetID(this MethodBase method, out bool contains)
{
// A > X = X1
// B > X = X2
if (!Mappings.ContainsKey(method))
{
var id = Mappings.Count;
Mappings.Add(method, Mappings.Count);
IDUsed.Add(id);
contains = false;
return id;
}
contains = true;
return Mappings[method];
}
public static int GetFreeID()
{
int id;
Random rnd = new Random();
do
{
id = rnd.Next();
} while (IDUsed.Contains(id));
IDUsed.Add(id);
return id;
}
public static BenchmarkCall GetCall(int id)
{
return TreeIDs[id]?.Call;
}
public static BenchmarkCall GetCall(this MethodBase method)
{
return TreeIDs[Mappings[method]]?.Call;
}
}
The BenchmarkEnumerator class allow us to differentiate between A or B, but it doesn't care about the full hierarchy, only from the parent MethodBase itself, so I need to write something complex to take in care of the full call stack, which I said I have a problem to understand.
Then we have the TargetMethods:
private static IEnumerable<MethodBase> TargetMethods()
{
Model = new BenchmarkTreeModel();
var sw = Stopwatch.StartNew();
//int i = 0;
return Filter.GetTargetMethods(method =>
{
try
{
var instructions = PatchProcessor.ReadMethodBody(method);
var i = method.GetID(out var contains);
var tree = new TreeModel
{
ID = i
};
if (contains)
{
//var lastId = i;
i = GetFreeID();
tree.ID = i;
tree.FillMethodName($"{method.GetMethodSignature()}_{i}"); // TODO: Check this
tree.Parent = null;
tree.Children = TreeMappings[method].Forest.First().Children; // ??
//DictionaryHelper.AddOrAppend(TreeMappings, method, tree);
TreeMappings[method].Forest.Add(tree);
TreeIDs.Add(i, tree);
Model.Forest.Add(tree);
// UNIT TESTING: All contained methods at this point will have a parent.
// string.Join is being added as a method by a instruction, so when we try to patch it, it will have already a reference on the dictionary
// Here, we check if the method was already added by a instruction CALL
// Logic: If the method is already contained by the mapping dictionary
// then, we will exit adding a new that will have the same childs but a new ID
return false;
}
TreeIDs.Add(i, tree);
tree.FillMethodName($"{method.GetMethodSignature()}_{i}"); // TODO: Check this
foreach (var pair in instructions)
{
var opcode = pair.Key;
if (opcode != OpCodes.Call || opcode != OpCodes.Callvirt) continue;
var childMethod = (MethodBase)pair.Value;
var id = childMethod.GetID(out var _contains);
var subTree = new TreeModel(tree)
{
ID = id
};
if (_contains)
{
id = GetFreeID();
subTree.ID = id;
subTree.FillMethodName($"{childMethod.GetMethodSignature()}_{id}"); // TODO: Check this
subTree.Parent = TreeIDs[i];
subTree.Children = TreeMappings[childMethod].Forest.First().Children;
TreeIDs.Add(id, subTree);
continue;
}
TreeIDs.Add(id, subTree);
subTree.FillMethodName($"{childMethod.GetMethodSignature()}_{id}");
tree.Children.Add(subTree);
TreeMappings.Add(childMethod, new BenchmarkTreeModel());
TreeMappings[childMethod].Forest.Add(subTree);
}
TreeMappings.Add(method, new BenchmarkTreeModel());
TreeMappings[method].Forest.Add(tree);
Model.Forest.Add(tree);
return true;
//var treeModel = new TreeModel();
}
catch (Exception ex)
{
//Debug.LogException(new Exception(method.GetMethodSignature(), ex));
return false;
}
}, sw);
//return methods;
}
The GetMethodSignature is something like:
public static string GetMethodSignature(this MethodBase method)
{
if (method == null) return null;
return method.DeclaringType == null ? method.Name : $"{method.DeclaringType.FullName}.{method.Name}";
}
I think I'll replace it with the MethodBase.ToString instead (what do you think?)
Also, we have the BenchmarkCall class which allow us to take in care how many times the call was done and how many time it has spent at all:
[Serializable]
public class BenchmarkCall
{
public string Method { get; set; }
public double SpentMilliseconds { get; set; }
public long SpentTicks { get; set; }
public double MinSpentMs { get; set; } = double.MaxValue;
public double MaxSpentMs { get; set; } = double.MinValue;
public long MinSpentTicks { get; set; } = long.MaxValue;
public long MaxSpentTicks { get; set; } = long.MinValue;
public double AvgMs => SpentMilliseconds / TimesCalled;
public double AvgTicks => SpentTicks / (double)TimesCalled;
public BenchmarkCall()
{
}
public BenchmarkCall(MethodBase method)
{
Method = method.GetMethodSignature();
}
public override string ToString()
{
if (TimesCalled > 0)
return "BenchmarkCall{\n" +
$"Ticks[SpentTicks={SpentTicks},MinTicks={MinSpentTicks},MaxTicks={MaxSpentTicks},AvgTicks={AvgTicks:F2}]\n" +
$"Ms[SpentMs={SpentMilliseconds:F2},MinMs={MinSpentMs:F2},MaxMs={MaxSpentMs:F2},AvgMs={AvgMs:F2}]\n" +
"}";
return "BenchmarkCall{}";
}
}
}
So I think that my next movement will be to differentiate between X method being called from A or B (Xa or Xb) taking care of the full hierarchy (which I'm not sure how to do) instead of the parent method that calls it, maybe the code I wrote has some to do it with it, but I'm not sure (last night I was so tired, so I didn't code it taking care those facts), build up a list of method signatures with different IDs, and then fill up the tree, ID 1 is Xa and ID 2 is Xb (where I have problems also filling up the tree).
Also I'll need to use the Transpiler in order to alter all code instructions, so if a method has:
void method() {
X1();
X2();
}
We will need to add 2 methods (like prefix/postfix) to measure each instruction call:
void method() {
Start(1);
X1();
End(1);
Start(2);
X2();
End(2);
}
This will be a hard task, but I hope somebody could guide me with this out.
With "Best Way" I mean, maybe, without many If, clean code.
I have a function that receives as parameters (string currentVersion, string action)
and it should return a string versionToBe = "";
For action = "installOldVersion"
-------------if "currentVersion"----------------: -------------OldversionToInstall--------------
"windows10(pro)", "windows10(pro)(education)" : "windows81(pro)"
"windows10(enterprise)", "windows10(enterpise)(lstb)" : "windows81(enterprise)"
"windows7(home)", "windows7(home)(basic)", "windows7(basic)", "windows7": "windowsVista(starter)"
"windowsXP(starter)", "windowsXP(starter)(home)", "windowsXP(home)", "windowsXP": "windows2000(professional)"
"windowsNT(workstation)", "windowsNT": "windows95(sp1)"
For action = "installNewVersion"
-------------if "currentVersion"----------------: -------------NewVersionToInstall--------------
"windows81(pro)", "windows81(pro)(education)" : "windows10(pro)"
"windows81(enterprise)", "windows81(enterprise)(education)" : "windows10(enterprise)"
"windowsVista(starter)", "windowsVista(starter)(package)", "windowsVista(package)", "windowsVista": "windows7(home)"
"windowsVista(starter)", "windowsVista(starter)(praok)", "windowsVista(praok)", "windowsVista": "windowsXP(starter)"
"windows95(sp1)", "windows95(sp1)(versionE)", "windows95": "windowsNT(workstation)"
So,for example, everytime the string name comes like: "windows10(pro)" or "windows10(pro)(education)" it should return: "windows81(pro)".
I know this can get done with lots of if like:
if (version.Equals("windows10(pro)") || version.Equals("windows10(pro)(education)"))
{
versionToBe = "windows81(pro)";
}
and the same for the rest of them, anding with 10 If statements in Total.
But If there's a better way to do it, I'd want to know.
Another restriction, or other thing to consider:
if the action is "installOldVersion", versionToBe is OldversionToInstall,
and if the action is "installNewVersion", versionTobe would be NewVersionToInstall.
You could create a list of objects with CurrentVersion, Old Version and New Version and then extract the one you want from the list.
Example Instruction Class Definition
public class VersionInformation
{
public string CurrentVersion {get; set;}
public string NewVersion {get; set;}
public string OldVersion {get; set;}
}
then in your program, have a list of them, either hard coded or loaded from file or whatever datastore you want and do your version check as follows:
private List<VersionInformation> _versionInformation = //Load your list from wherever;
public void DoVersionCheck(string version)
{
var currentversionInfo = _versionInformation.Single(x=> x.CurrentVersion == version);
//Do Whatever you want with the upgrades and downgrades here based on whatever action you are doing
}
Set yourself up a dictionary and perform a lookup.
As an exercise for the reader:
You could drive the dictionary contents from some configuration or other...even from a database if you want.
You'd presumably want to set up your dictionary as a static and initialize it only once.
You'll want some handling for when there is no dictionary entry - you don't specify a default in your question.
Dictionary, string> ActionMatrix = new Dictionary, string>();
ActionMatrix.Add(Tuple.Create ("windows10(pro)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(pro)(education)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(enterprise)", "installOldVersion"), "windows81(enterprise)");
ActionMatrix.Add(Tuple.Create ("windows10(enterpise)(lstb)", "installOldVersion"), "windows81(enterprise)");
// etc
ActionMatrix.Add(Tuple.Create("windows81(pro)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(pro)(education)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(enterprise)", "installNewVersion"), "windows10(enterprise)");
ActionMatrix.Add(Tuple.Create("windows10(enterpise)(education)", "installNewVersion"), "windows10(enterprise)");
// etc
public string VersionToBe (string currentVersion, string action)
{
return ActionMatrix[Tuple.Create(currentVersion, action)];
}
A simple object with it's own list should do the trick and is visually better to follow.
public class VersionData
{
private static List<VersionData> VersionDatas { get; set; } = new List<VersionData>()
{
new VersionData( "OldversionToInstall", new [] {"windows10(pro)", "windows10(pro)(education)" }.ToList(), "windows81(pro)" ),
new VersionData( "OldversionToInstall", new [] {"windows10(enterprise)", "windows10(enterpise)(lstb)" }.ToList(), "windows81(enterprise)" )
};
public string Action { get; set; } = "";
public List<string> CurrentVersions { get; set; } = new List<string>();
public string Version { get; set; } = "";
public VersionData(string action, List<string> currentVersions, string version)
{
Action = action;
CurrentVersions = currentVersions;
Version = version;
}
public static string GetVersion(string action, string currentVersion)
{
return VersionDatas.FirstOrDefault(o => o.Action == action && o.CurrentVersions.Any(x => x == currentVersion)).Version;
}
}
and to call it's as simple as :
var oldVersion = VersionData.GetVersion("OldversionToInstall", "windows10(enterpise)(lstb)");
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 was looking for a way to switch my assignments i.e:
a = b;
becomes
b = a;
In case anyone is wondering, it's for loading settings and unloading them.
I crafted a regular expression for it:
Find what: {[^:b]*} = {[^;]*}
Replace with: \2 = \1
This works fine, but is there another way to load and save settings that I'm missing?
An alternative approach: what about making a settings class with a method that copies values? In that way you write the list of assignments only once:
using System;
class Settings {
public int ValueA { get; set; }
public string ValueB { get; set; }
public void CopySettings(Settings other) {
ValueA = other.ValueA;
ValueB = other.ValueB;
}
}
class Program {
static void Main(string[] args) {
Settings a = new Settings() { ValueA = 3, ValueB = "something" };
Settings b = new Settings();
// and then you can do one the following, which will copy all settings
// in both cases...
b.CopySettings(a);
a.CopySettings(b);
}
}
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).