I'm attempting to use a custom attribute to generate a list of commands (string) that a user would issue into my console application and the corresponding method will be executed. I'm currently stuck, my command list is always empty.
Here's my attribute:
public class ImporterAttribute : Attribute
{
public string Command { get; set; }
}
Here's the class:
public class DataProcessor
{
public List<ImporterAttribute> Commands { get; set; }
public DataProcessor()
{
//Use reflection to collect commands from attributes
Commands = GetCommands(typeof(DataProcessor));
}
public static List<ImporterAttribute> GetCommands(Type t)
{
var commands = new List<ImporterAttribute>();
MemberInfo[] MyMemberInfo = t.GetMethods();
foreach (MemberInfo member in MyMemberInfo)
{
var att = (ImporterAttribute)Attribute.GetCustomAttribute(member, typeof(ImporterAttribute));
if (att == null) continue;
var command = new ImporterAttribute();
command.Command = att.Command;
commands.Add(command);
}
return commands;
}
[Importer(Command = "?")]
private string Help()
{
return "Available commands: " + (from c in Commands select c.Command).Aggregate((a, x) => a + " " + x);
}
[Importer(Command = "Q")]
private void Quit()
{
Environment.Exit(0);
}
}
Then I use a switch statement to check user input against the command list and run the requested method. So my question is: why is my command list always null? I imagine I just misunderstood something in the docs.
Bonus question: does anyone have a better/more practical approach that they use/have used to tackle this feature?
The problem with your code is that your methods are private. GetMethods by default only retrieve public methods, so if you change your Help and Quit method signature to public, you'll get 2 commands.
If you want to keep them private,you can use BindingFlags like this:
t.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
Related
I have a snippet that executes a PowerShell script
using (var ps = PowerShell.Create())
{
ps.AddScript("function Test() { return Get-Disk -Number 0 } ");
ps.Invoke();
ps.AddCommand("Test");
var results = ps.Invoke();
var disk = results.First();
MyDisk myDisk = // do something to convert disk to myDisk
}
Debuggin, it get his inside disk:
How I'm supposed to deal with this object (CimObject)? I would like to get the values from the "Name" and "Number" properties.
Just to clarify, the object I'm trying to deal is the same type as this (run into PowerShell as admin)
PS C:\windows\system32> $disk = Get-Disk -Number 0
PS C:\windows\system32> $disk.GetType();
How do I interact with this?
Thank you!
I don't think there is any easy way to convert PowerShell output to an easier to handle format. You need to 'manually' pull out the properties you want. For example, you can get the 'AllocatedSize' value like this:
var allocatedSize = results.First().Members["AllocatedSize"].Value;
If you want your own types based on these values, then you can do something like this:
Define your type (change the properties to suit the ones you want):
public class MyDisk
{
public long AllocatedSize { get; set; }
public string FriendlyName { get; set; }
public bool IsBoot { get; set; }
public int Number { get; set; }
}
Add a helper method that does the conversion:
private static MyDisk ConvertToMyDisk(PSMemberInfoCollection<PSMemberInfo> item)
{
return new MyDisk
{
AllocatedSize = long.Parse(item["AllocatedSize")].Value.ToString()),
FriendlyName = item["FriendlyName"].Value.ToString(),
IsBoot = bool.Parse(item["IsBoot"].Value.ToString()),
Number = int.Parse(item["Number"].Value.ToString())
};
}
You can then convert the return values to your own type with some basic LINQ:
List<MyDisk> myDisks = results.Select(d => ConvertToMyDisk(d.Members)).ToList();
im currently expanding my knowledge a little, and wanted to Create a little game for myself.
The Structure is as Following:
Programm.cs creates an instance of Gamecontroller. This Gamecontroller is the lowest level i want to Access. It will create instaces of the Views, and from classes like config.
I want to implement an debug Console with Command Input. These Commands should always start at the Gamecontroller level, and should be able to interact with kinda everything i could do with C# code.
So i want to access the Objects, Member and methods withing Gamecontroller, or Within any nested object.
Currently i cant get to the Properties of an Child, because _member returns an "Type" which gets parsed to RuntimeProperty instead of the Class
Example on Parsing:
"objPlayer.name" > "GameController.objPlayer.name"
"objConfig.someSetting = 10" > "GameController.objConfig.someSetting=10"
"objConfig.functionCall()" > "GameController.objConfig.functionCall()"
"objConfig.objPlayer.setName("someName")" > "GameController.objConfig.objPlayer.setName("someName")"
"objPlayer.name" > "GameController.objPlayer.name"
this is what i got so far:
private void parseComamnd(string Command)
{
var actions = Command.Split('.');
var start = this.GetType();
var last = actions[actions.Length - 1];
foreach (var action in actions)
{
if (action.Contains("(") && action.Contains(")"))
{
_exec(start, action);
}
else
{
start = _member(start, action);
}
}
}
private Type _member(Type pHandle, string pStrMember)
{
return pHandle.GetProperty(pStrMember).GetType();
}
private void _exec(Type pHandle, string pStrFunction)
{
var Regex = new Regex(#"\(|,|\)");
var FunctionParams = Regex.Split(pStrFunction);
var FunctionName = FunctionParams[0];
FunctionParams[0] = "";
FunctionParams = FunctionParams.Where(val => val != "").ToArray();
pHandle.GetMethod(FunctionName).Invoke(FunctionName, FunctionParams);
}
If I understood right, you want to match some string commands with actions you want to perform. In this case you could use Dictionary as a storage for string-delgate couples to match your string commands to actions you want to perform. As an advantage of this approach, you can change matched couples during program runtime as you wish
class SomeClass
{
delegate void OperationDelegate(string value);
IDictionary<string, OperationDelegate> Operations = new Dictionary<string, OperationDelegate>();
public SomeClass()
{
Operations.Add("objPlayer.name", SetName);
Operations.Add("objConfig.someSetting", SetSetting);
}
public void HandleNewValue(string command, string value)
{
try
{
if (Operations.ContainsKey(command))
Operations[command](value);
}
catch (Exception e)
{
Logger.Error(e);
}
}
private void SetName(string value)
{
// Some logic there
}
private void SetSetting(string value)
{
// Some logic there
}
}
I see a lot of similar questions but none with a direct answer. I have a List<ClientEntry>. I want to access properties in ClientEntry. My code looks like this:
class ClientEntry
{
private string _clientName;
private string _clientEmail;
public void ClientEntry(string name, string email)
{
this._clientName = name;
this._clientEmail = email;
}
public string ClientName
{
get
{
return _clientName;
}
set
{
_clientName = value;
}
}
public string ClientEmail
{
get
{
return _clientEmail;
}
set
{
RegexUtilities Validator = new RegexUtilities();
if (Validator.IsValidEmail(value))
{
_clientEmail = value;
}
}
}
}
Later:
private List<ClientEntry> clientList;
I then add a bunch of ClientEntry's to the List.
How can I access the ClientName and ClientEmail properties for items in clientList? Also, how can I check for the existance of a certain ClientName or ClientEmail property within the List? Is this even possible with a list of objects? I know a dict would probably serve better, but I wanted to see if this could be done with a List and a class with properties.
You can use Linq to look for values inside of a list using Any()
Eg.
bool emailExists = clientList.Any(x=>x.ClientEmail == <email>);
To access values, you can use a index accessor if you know it, loop the collection, or use Where() to search it:
var email = clientList[index].ClientEmail
or
foreach (var client in clientList)
{
var email = client.ClientEmail
}
or
var email = clientList.Where(x=>x.ClientName == <clientName>).FirstOrDefault();
you can explore your list as below
foreach (ClientEntry client in clientList)
{
//client.ClientName
//client.ClientEmail
}
to find a particular record you can search it as
clientList.Where(p=> p.ClientEmail == "email#domain.com").FirstOrDefault();
To access a specific of item in the list, you input the index / using foreach
string name = clientList[index].ClientName;
foreach(var client in clientList)
{
name = client.ClientName; // access the item one by one
}
To check the existence of certain value of a property, use linq
bool isExist = clientList.Any(i => i.ClientName == "John");
Use Extension Methods !
Something like this, you can write unit test against the extension class easily and also it's straightforward to read.
public static class ClientEntriesExtension
{
public static bool ExistEmail(this IEnumerable<ClientEntry> entries, string targetEmail)
{
return entries.Any(x=>x.ClientEmail == targetEmail);
}
}
bool exist = clientList.ExistEmail(targetEmail)
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).