Finding methods in source code using regular expressions - c#

I have a program which looks in source code, locates methods, and performs some calculations on the code inside of each method. I am trying to use regular expressions to do this, but this is my first time using them in C# and I am having difficulty testing the results.
If I use this regular expression to find the method signature:
((private)|(public)|(sealed)|(protected)|(virtual)|(internal))+([a-z]|[A-Z]|[0-9]|[\s])*([\()([a-z]|[A-Z]|[0-9]|[\s])*([\)|\{]+)
and then split the source code by this method, storing the results in an array of strings:
string[] MethodSignatureCollection = regularExpression.Split(SourceAsString);
would this get me what I want, ie a list of methods including the code inside of them?

I would strongly suggest using Reflection (if it is appropriate) or CSharpCodeProvider.Parse(...) (as recommended by rstevens)
It can be very difficult to write a regular expression that works in all cases.
Here are some cases you'd have to handle:
public /* comment */ void Foo(...) // Comments can be everywhere
string foo = "public void Foo(...){}"; // Don't match signatures in strings
private __fooClass _Foo() // Underscores are ugly, but legal
private void #while() // Identifier escaping
public override void Foo(...) // Have to recognize overrides
void Foo(); // Defaults to private
void IDisposable.Dispose() // Explicit implementation
public // More comments // Signatures can span lines
void Foo(...)
private void // Attributes
Foo([Description("Foo")] string foo)
#if(DEBUG) // Don't forget the pre-processor
private
#else
public
#endif
int Foo() { }
Notes:
The Split approach will throw away everything that it matches, so you will in fact lose all the "signatures" that you are splitting on.
Don't forget that signatures can have commas in them
{...} can be nested, your current regexp could consume more { than it should
There is a lot of other stuff (preprocessor commands, using statements, properties, comments, enum definitions, attributes) that can show up in code, so just because something is between two method signatures does not make it part of a method body.

Maybe it is a better approach to use the CSharpCodeProvider.Parse() which can "compile" C# source code into a CompileUnit.
You can then walk through the namespaces, types, classes and methods of in that Compile Unit.

using ICSharpCode.NRefactory.CSharp;
PM> install-package ICSharpCode.NRefactory
var parser = new CSharpParser();
var syntaxTree = parser.Parse(File.ReadAllText(sourceFilePath));
var result = syntaxTree.Descendants.OfType<MethodDeclaration>()
.FirstOrDefault(y => y.NameToken.Name == methodName);
if (result != null)
{
return result.ToString(FormattingOptionsFactory.CreateSharpDevelop()).Trim();
}

It is feasible, I guess, to get something working using regex's, however this does require looking very carefully at the specifications for the C# language and a deep understanding of the C# grammar, this is not a simple problem. I know you've said you want to store the methods as arrays of strings, but presumably there is something beyond that. It has already been pointed out to look at using reflection, however if that does not do what you want, you should consider ANTLR (ANother Tool for Language Recognition). ANTLR does have C# grammars available.
http://www.antlr.org/about.html

No, those access modifiers can also be used for internal classes and fields, among other things. You'd need to write a full C# parser to get it right.
You can do what you want using reflection. Try something like the following:
var methods = typeof (Foo).GetMethods();
foreach (var info in methods)
{
var body = info.GetMethodBody();
}
That probably has what you need for your calculations.
If you need the original C# source code you can't get it with reflection. Don't write your own parser. Use an existing one, listed here.

Related

How to attach functions together in C#?

I am having a hard time understanding this piece of code:
public IObservable<SomeInfo> OriginalFunction() => FirstFunction().SecondFunction(argument1).ThirdFunction(argument2);
First, I don't understand what that IObservable<CarsInfo> means. Does this function return an observable?
Then, what does the lambda => do?
And finally, how are the three functions attached to each other using dots?
public IObservable<SomeInfo> OriginalFunction() => FirstFunction().SecondFunction(argument1).ThirdFunction(argument2);
is equivalent to
public IObservable<SomeInfo> OriginalFunction()
{
var firstResult = FirstFunction();
var secondResult = firstResult.SecondFunction(argument1)
return secondResult.ThirdFunction(argument2); // mind the 'return' here!
}
which by the way expect argument1 and argument2 as class fields or properties, which some people would consider "not so clean"*.
* I should elaborate on that: While clean code advocates for having as small number of arguments as possible, using class fields or properties here does make the function harder to test. I personally would consider this a kind of side-effect which should be avoided. What do I mean by side-effect? Two calls of this function may return different results depending on the value of class fields. This could be reasonable or not. Depends on the actual semantics of the code which is not at all clear from the example.
So, TL;DR: Consider if it is reasonable to use class fields or if it is more reasonable to to use two arguments or use an "Options-Pattern" argument. Take into account: Is it clear what result to expect ("do not surprise clients")? Is the function testable? And some more...
EDIT:
=> is a feature added in C# 6.0 : Expression-bodied function members
Many members that you write are single statements that could be single expressions. Write an expression-bodied member instead. It works for methods and read-only properties. For example, an override of ToString() is often a great candidate:
public override string ToString() => $"{LastName}, {FirstName}";

Is it good practice to cast objects to dynamic so the correct overloaded method is called?

My question is about whether what follows is an appropriate use of the dynamic keyword in C# 4.
I have some helper methods that provide a more useful representation of various objects than their standard ToString methods do, which I use for unit testing. Here is a simplified example:
public static string PrettyPrint<T>(IEnumerable<T> list)
{
return string.Join(", ", list);
}
// Needed because string is IEnumerable<char>, to prevent
// "Hello" -> "H, e, l, l, o"
public static string PrettyPrint(string s)
{
return s;
}
public static string PrettyPrint(object o)
{
return o.ToString();
}
I use them something like this:
public static void PrettyPrinting()
{
object[] things = { 1, "Hello", new int[] {1, 2, 3} };
foreach (dynamic item in things)
{
Console.WriteLine(PrettyPrint(item));
}
}
This produces the following output:
1
Hello
1, 2, 3
Notice that if I replace the dynamic keyword with object, I get the following (all the calls are routed through PrettyPrint(object)), which is what I am trying to avoid:
1
Hello
System.Int32[]
So my question is essentially is this a code smell or is it legitimate to cast an object to dynamic in this way?
So long as you don't abuse it, duck typing like this is part of the reason dynamic was added to the language.
As to your question, I'm not 100% sure as I don't know your teams style of coding. (I also see little comments ;) )
DuckTyping has it's uses - however a developer needs to know what they're doing before using it. Otherwise it's like running with scissors; it could be abused like other keywords in the C# system.
Personally, I'd rather see extension methods, but depending on the developer, his/her arguments and the documentation done I'd probably allow it.
The biggest reason for my hesitation (and this example is pretty tame to some of the ones I've seen online) is it stops you from finding issues at compile time. It requires more QA testing, a lot more boundary testing, and has a higher risk of failure.
Not an answer to the exact question, but I would say your code is not very OO, which is another smell.
Ideally you want to call item.PrettyPrint() and each item is supposed to return its representation, and override PrettyPrint.
Luckily, existing types can be extended with extension methods. They enable you to add the methods and that's what I would do instead.
If you still want to have the logic for the display of each type in one class, I would combine extension methods with the visitor pattern.
That said, I don't have C# environment so I can't test what I propose. Let me know if you try this, and if it works.

Regex: C# method declaration parsing

Could somebody help me parse following from the C# method declaration: scope, isStatic, name, return type and list of the parameters and their types. So given method declaration like this
public static SomeReturnType GetSomething(string param1, int param2)
etc. I need to be able to parse it and get the info above. So in this case
name = "GetSomething"
scope = "public"
isStatic = true
returnType = "SomeReturnType"
and then array of parameter type and name pairs.
Oh almost forgot the most important part. It has to account for all other scopes (protected, private, internal, protected internal), absence of "static", void return type etc.
Please note that REFLECTION is not solution here. I need REGEX.
So far I have these two:
(?:(?:public)|(?:private)|(?:protected)|(?:internal)|(?:protected internal)\s+)*
(?:(?:static)\s+)*
I guess for rest of the problem I can just get away with string manipulation without regex.
Some thoughts on your problem:
A set of strings that can all be matched by a particular regular expression is called a regular language. The set of strings which are legal method declarations is not a regular language in any version of C#. If you are attempting to find a regular expression which matches every legal C# method declaration and rejects every illegal C# method declaration then you are out of luck.
More generally, regular expressions are almost always a bad idea for anything but the simplest matching problems. (Sorry Jeff.) A far better approach is to first write a lexer, which breaks up the string into a sequence of tokens. Then analyze the token sequence. (Using regular expressions as part of a lexer is not a terrible idea, though you can get by without them.)
I note also that you are glossing over rather a lot of complications in parsing method declarations. You did not mention:
generic/array/pointer/nullable return and formal parameter types
generic type parameter declarations
generic type parameter constraints
unsafe/extern/new/override/virtual/abstract/sealed methods
explicit interface implementation methods
method/parameter/return attributes
partial methods -- slightly tricky to parse, partial is a contextual keyword
comments
I also note that you've not said whether you are guaranteed that the method signature is already good, or if you need to identify bad ones and produce diagnostics as to why they're bad. That's a much harder problem.
Why do you want to do this in the first place? Doing this correctly is rather a lot of work. Perhaps there is an easier way to get what you want?
I wouldn't bother with using Regex. When you get to the part of interpreting method parameters, it gets really messy (ref and out keywords for example). I don't know if you need support for attribute notation as well, but that would make it a complete mess.
Maybe a C# parser library can be of help. I've found a few on the internet:
http://www.codeplex.com/csparser (C# 1.0)
http://www.csharpparser.com/
Alternatively, you could first feed the code to the compiler at runtime, and then use reflection on the newly created assembly. It will be slower, but pretty much guaranteed to be correct. Even though you seem to be opposed to the idea of using reflection, this can be a viable solution.
Something like this:
List<string> referenceAssemblies = new List<string>()
{
"System.dll"
// ...
};
string source = "public abstract class TestClass {" + input + ";}";
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
// No assembly name specified
CompilerParameters compilerParameters =
new CompilerParameters(referenceAssemblies.ToArray());
compilerParameters.GenerateExecutable = false;
compilerParameters.GenerateInMemory = false;
CompilerResults compilerResults = codeProvider.CompileAssemblyFromSource(
compilerParameters, source);
// Check for successful compilation here
Type testClass = compilerResults.CompiledAssembly.GetTypes().First();
Then use reflection on testClass.
Compiling should be safe without input validation, because you're not executing any of the code. You'd only need very basic checks, such as making sure only 1 method signature is entered.
Well given the rules you've provided, it would probably be best to use a series of regular expressions rather than trying to come up with a singular expression. That expression would be enormous.
If you're sold on a singular expression, you'll need to use a regular expression that uses grouping, look-ahead and look-behind.
http://www.regular-expressions.info/lookaround.html
Even with the limited scope of what you're trying to parse out of it, you'll still need some very specific guidelines on all possibilities.
string test = #"public static SomeReturnType GetSomething(string param1, int param2)";
var match = Regex.Match(test, #"(?<scope>\w+)\s+(?<static>static\s+)?(?<return>\w+)\s+(?<name>\w+)\((?<parms>[^)]+)\)");
Console.WriteLine(match.Groups["scope"].Value);
Console.WriteLine(!string.IsNullOrEmpty(match.Groups["static"].Value));
Console.WriteLine(match.Groups["return"].Value);
Console.WriteLine(match.Groups["name"].Value);
List<string> parms = match.Groups["parms"].ToString().Split(',').ToList();
parms.ForEach(x => Console.WriteLine(x));
Console.Read();
Broken for parms with commas, but it's quite possible to also handle that.
(?<StringRepresentation>\A\s*(?:(?:(?<Comment>(?://.*\n)|(?:/\*(?:[\w\d!##$%^&*()\[\]<>,.;\\"':|{}`~+=-_?\s]*)?\*/))|(\[\s*(?<Attributes>\w*)[^\[\]]*?\]))\s*)*?(?:(?:(?<Access>protected\s+internal|internal\s+protected|private|public|protected|internal)\s+)?(?:(?<InheritanceModifier>new|abstract|override|virtual)\s+)?(?:(?<Static>static)\s+)?(?:(?<Extern>extern)\s+)?(?:partial\s+)?)+(?:(?<Type>\w+(?:[\w,.\?\[\]])*?(?:\<.*>)*?)\s+)?(?<Operator>operator\s+)?\s*(?<Name>~?(?:[\w\=+\-\!\~\d\.])+?)\s*(?:\<(?:\w\.*\d*\,*\s*)+\>)*\s*\((?<Parameters>(?:[^()])*?)\)\s*(?:where\s+.+)?\s*(?:\:\s*(?:this|base)\s*(?:\(?[^\(\)]*(?:(?:(?:(?<OpenC>\()[^\(\)]*)+(?:(?<CloseC-OpenC>\))[^\(\)]*?)+)*(?(OpenC)(?!))\)))\s*)?(?:;|(?<ah>\{[^\{\}]*(?:(?:(?:(?<Open>\{)[^\{\}]*)+(?:(?<Close-Open>\})[^\{\}]*?)+)*(?(Open)(?!))\}))))
I can't personally take credit for this one, but the guy who made Regionerate (open source) came up with this and it works pretty well for parsing methods in general.

Is there an easy way to parse a (lambda expression) string into an Action delegate?

I have a method that alters an "Account" object based on the action delegate passed into it:
public static void AlterAccount(string AccountID, Action<Account> AccountAction) {
Account someAccount = accountRepository.GetAccount(AccountID);
AccountAction.Invoke(someAccount);
someAccount.Save();
}
This works as intended...
AlterAccount("Account1234", a => a.Enabled = false);
...but now what I'd like to try and do is have a method like this:
public static void AlterAccount(string AccountID, string AccountActionText) {
Account someAccount = accountRepository.GetAccount(AccountID);
Action<Account> AccountAction = MagicLibrary.ConvertMagically<Action<Account>>(AccountActionText);
AccountAction.Invoke(someAccount);
someAccount.Save();
}
It can then be used like:
AlterAccount("Account1234", "a => a.Enabled = false");
to disable account "Account1234".
I've had a look at the linq dynamic query library, which seems to do more or less what I want but for Func type delegates, and my knowledge of Expression trees etc isn't quite good enough to work out how to achieve what I want.
Is there an easy way to do what I want, or do I need to learn expressions properly and write a load of code?
(The reason I want to do this is to allow an easy way of bulk updating account objects from a powershell script where the user can specify a lambda expression to perform the changes.)
The Dynamic LINQ library is a fine choice, as it'll generate expressions you can compile to code in a lightweight fashion.
The example you provided actually produces a boolean -- so you should be able to ask for a Func and it might sort it out.
Edit: This of course is wrong, as Expressions don't have assignment in them at all.
So, another potential way is to take two lambdas. One to find the property you want, one to provide a value:
(a => a.AccountId), (a => true)
Then use reflection to set the property referenced in the first lambda with the result of the second one. Hackish, but it's still probably lightweight compared to invoking the C# compiler.
This way you don't have to do much codegen yourself - the expressions you get will contain most everything you need.
You may try this: Dynamic Lambda Expressions Using An Isolated AppDomain
It compiles a lambda expression using CodeDOM compiler. In order to dispose the in-memory assembly that gets created, the compiler runs on an isolated AppDomain. For the passing the expression through the domain boundary, it has to be serialized. Alas, Expression<> is not Serializable. So, a trick has to be used. All the details are explained in the post.
I'm the author of that component, by the way. I would like very much to hear your feedback from it.
There is no general way to parse a string into a lambda expression without a full compilation, because lambda expressions can reference things that are defined outside the lambda expression. I know of no library that handles the specific case you want. There's a long discussion of this on a thread on a C# discussion group.
The easiest way to get what you want is to compile a method at runtime. You can write a function that takes in the string "a.Enabled = true; return a;" and sticks that in the middle of a function that takes an Account as a parameter. I would use this library as a starting point, but you can also use the function mentioned on another thread.
That's easy:
Use CodeDom to generate the module containing the "surrounding class" you'll use to build the expression; this class must implement the interface known to your application
Use CodeSnippedExpression to inject the expression into its member.
Use Activator type to create the instance of this class in runtime.
Basically, you need to build the following class with CodeDom:
using System;
using MyNamespace1;
using ...
using MyNamespace[N];
namespace MyNamespace.GeneratedTypes
{
public class ExpressionContainer[M] : IHasAccountAction
{
public Action<Account> AccountAction {
get {
return [CodeSnippedExpression must be used here];
}
}
}
}
Assuming that IHasAccountAction is:
public IHasAccountAction {
public Action<Account> AccountAction { get; }
}
If this is done, you can get the expression compiled from string with ease. If you need its expression tree representation, use Expression<Action<Account>> instead of Action<Account> in generated type.

C# Preprocessor

While the C# spec does include a pre-processor and basic directives (#define, #if, etc), the language does not have the same flexible pre-processor found in languages such as C/C++. I believe the lack of such a flexible pre-processor was a design decision made by Anders Hejlsberg (although, unfortunately, I can't find reference to this now). From experience, this is certainly a good decision, as there were some really terrible un-maintainable macros created back when I was doing a lot of C/C++.
That said, there are a number of scenarios where I could find a slightly more flexible pre-processor to be useful. Code such as the following could be improved by some simple pre-processor directives:
public string MyProperty
{
get { return _myProperty; }
set
{
if (value != _myProperty)
{
_myProperty = value;
NotifyPropertyChanged("MyProperty");
// This line above could be improved by replacing the literal string with
// a pre-processor directive like "#Property", which could be translated
// to the string value "MyProperty" This new notify call would be as follows:
// NotifyPropertyChanged(#Property);
}
}
}
Would it be a good idea to write a pre-processor to handle extremely simple cases like this? Steve McConnell wrote in Code Complete (p208):
Write your own preprocessor If a language doesn't include a preprocessor, it's fairly easy to write one...
I am torn. It was a design decision to leave such a flexible pre-processor out of C#. However, an author I highly respect mentions it may be ok in some circumstances.
Should I build a C# pre-processor? Is there one available that does the simple things I want to do?
Consider taking a look at an aspect-oriented solution like PostSharp, which injects code after the fact based on custom attributes. It's the opposite of a precompiler but can give you the sort of functionality you're looking for (PropertyChanged notifications etc).
Should I build a C# pre-processor? Is there one available that does the simple things I want to do?
You can always use the C pre-processor -- C# is close enough, syntax-wise. M4 is also an option.
I know a lot of people think short code equals elegant code but that isn't true.
The example you propose is perfectly solved in code, as you have shown so, what do you need a preprocessor directive to? You don't want to "preprocess" your code, you want the compiler to insert some code for you in your properties. It's common code but that's not the purpose of the preprocessor.
With your example, Where do you put the limit? Clearly that satisfies an observer pattern and there's no doubt that will be useful but there are a lot of things that would be useful that are actually done because code provides flexibility where as the preprocessor does not. If you try to implement common patterns through preprocessor directives you'll end with a preprocessor which needs to be as powerful as the language itself. If you want to process your code in a different way the use a preprocessor directive but if you just want a code snippet then find another way because the preprocessor wasn't meant to do that.
Using a C++-style preprocessor, the OP's code could be reduced to this one line:
OBSERVABLE_PROPERTY(string, MyProperty)
OBSERVABLE_PROPERTY would look more or less like this:
#define OBSERVABLE_PROPERTY(propType, propName) \
private propType _##propName; \
public propType propName \
{ \
get { return _##propName; } \
set \
{ \
if (value != _##propName) \
{ \
_##propName = value; \
NotifyPropertyChanged(#propName); \
} \
} \
}
If you have 100 properties to deal with, that's ~1,200 lines of code vs. ~100. Which is easier to read and understand? Which is easier to write?
With C#, assuming you cut-and-paste to create each property, that's 8 pastes per property, 800 total. With the macro, no pasting at all. Which is more likely to contain coding errors? Which is easier to change if you have to add e.g. an IsDirty flag?
Macros are not as helpful when there are likely to be custom variations in a significant number of cases.
Like any tool, macros can be abused, and may even be dangerous in the wrong hands. For some programmers, this is a religious issue, and the merits of one approach over another are irrelevant; if that's you, you should avoid macros. For those of us who regularly, skillfully, and safely use extremely sharp tools, macros can offer not only an immediate productivity gain while coding, but downstream as well during debugging and maintenance.
The main argument agaisnt building a pre-rocessor for C# is integration in Visual Studio: it would take a lot of efforts (if at all possible) to get intellisense and the new background compiling to work seamlessly.
Alternatives are to use a Visual Studio productivity plugin like ReSharper or CodeRush.
The latter has -to the best of my knowledge- an unmatched templating system and comes with an excellent refactoring tool.
Another thing that could be helpful in solving the exact types of problems you are referring to is an AOP framework like PostSharp.
You can then use custom attributes to add common functionality.
To get the name of the currently executed method, you can look at the stack trace:
public static string GetNameOfCurrentMethod()
{
// Skip 1 frame (this method call)
var trace = new System.Diagnostics.StackTrace( 1 );
var frame = trace.GetFrame( 0 );
return frame.GetMethod().Name;
}
When you are in a property set method, the name is set_Property.
Using the same technique, you can also query the source file and line/column info.
However, I did not benchmark this, creating the stacktrace object once for every property set might be a too time consuming operation.
I think you're possibly missing one important part of the problem when implementing the INotifyPropertyChanged. Your consumer needs a way of determining the property name. For this reason you should have your property names defined as constants or static readonly strings, this way the consumer does not have to `guess' the property names. If you used a preprocessor, how would the consumer know what the string name of the property is?
public static string MyPropertyPropertyName
public string MyProperty {
get { return _myProperty; }
set {
if (!String.Equals(value, _myProperty)) {
_myProperty = value;
NotifyPropertyChanged(MyPropertyPropertyName);
}
}
}
// in the consumer.
private void MyPropertyChangedHandler(object sender,
PropertyChangedEventArgs args) {
switch (e.PropertyName) {
case MyClass.MyPropertyPropertyName:
// Handle property change.
break;
}
}
If I were designing the next version of C#, I'd think about each function having an automatically included local variable holding the name of the class and the name of the function. In most cases, the compiler's optimizer would take it out.
I'm not sure there's much of a demand for that sort of thing though.
#Jorge wrote: If you want to process your code in a different way the use a preprocessor directive but if you just want a code snippet then find another way because the preprocessor wasn't meant to do that.
Interesting. I don't really consider a preprocessor to necessarily work this way. In the example provided, I am doing a simple text substitution, which is in-line with the definition of a preprocessor on Wikipedia.
If this isn't the proper use of a preprocessor, what should we call a simple text replacement, which generally needs to occur before a compilation?
At least for the provided scenario, there's a cleaner, type-safe solution than building a pre-processor:
Use generics. Like so:
public static class ObjectExtensions
{
public static string PropertyName<TModel, TProperty>( this TModel #this, Expression<Func<TModel, TProperty>> expr )
{
Type source = typeof(TModel);
MemberExpression member = expr.Body as MemberExpression;
if (member == null)
throw new ArgumentException(String.Format(
"Expression '{0}' refers to a method, not a property",
expr.ToString( )));
PropertyInfo property = member.Member as PropertyInfo;
if (property == null)
throw new ArgumentException(String.Format(
"Expression '{0}' refers to a field, not a property",
expr.ToString( )));
if (source != property.ReflectedType ||
!source.IsSubclassOf(property.ReflectedType) ||
!property.ReflectedType.IsAssignableFrom(source))
throw new ArgumentException(String.Format(
"Expression '{0}' refers to a property that is not a member of type '{1}'.",
expr.ToString( ),
source));
return property.Name;
}
}
This can easily be extended to return a PropertyInfo instead, allowing you to get way more stuff than just the name of the property.
Since it's an Extension method, you can use this method on virtually every object.
Also, this is type-safe.
Can't stress that enough.
(I know its an old question, but I found it lacking a practical solution.)
While there are plenty of good reflection-based answers here, the most obvious answer is missing and that is to use the compiler, at compile time.
Note that the following method has been supported in C# and .NET since .NET 4.5 and C# 5.
The compiler does in fact have some support for obtaining this information, just in a slightly roundabout way, and that is through the CallerMemberNameAttribute attribute. This allows you to get the compiler to inject the name of the member that is calling a method. There are two sibling attributes as well, but I think an example is easier to understand:
Given this simple class:
public static class Code
{
[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static string MemberName([CallerMemberName] string name = null) => name;
[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static string FilePath([CallerFilePathAttribute] string filePath = null) => filePath;
[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static int LineNumber([CallerLineNumberAttribute] int lineNumber = 0) => lineNumber;
}
of which in the context of this question you actually only need the first method, you can use it like this:
public class Test : INotifyPropertyChanged
{
private string _myProperty;
public string MyProperty
{
get => _myProperty;
set
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Code.MemberName()));
_myProperty = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Now, since this method is only returning the argument back to the caller, chances are that it will be inlined completely which means the actual code at runtime will just grab the string that contains the name of the property.
Example usage:
void Main()
{
var t = new Test();
t.PropertyChanged += (s, e) => Console.WriteLine(e.PropertyName);
t.MyProperty = "Test";
}
output:
MyProperty
The property code actually looks like this when decompiled:
IL_0000 ldarg.0
IL_0001 ldfld Test.PropertyChanged
IL_0006 dup
IL_0007 brtrue.s IL_000C
IL_0009 pop
IL_000A br.s IL_0021
IL_000C ldarg.0
// important bit here
IL_000D ldstr "MyProperty"
IL_0012 call Code.MemberName (String)
// important bit here
IL_0017 newobj PropertyChangedEventArgs..ctor
IL_001C callvirt PropertyChangedEventHandler.Invoke (Object, PropertyChangedEventArgs)
IL_0021 ldarg.0
IL_0022 ldarg.1
IL_0023 stfld Test._myProperty
IL_0028 ret
Under VS2019, you do get enhanced ability to precompile, without losing intellisense, when using a generator (see https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/).
For example: if you would be in need to remove readonly keywords (useful when manipulating constructors), then your generator could act as a precompiler to remove these keywords at compile time and generate the actual source that is to be compiled instead.
Your original source would then look like the following (the §RegexReplace macro is to be executed by the Generator and subsequently commented out in the generated source):
#if Precompiled || DEBUG
#if Precompiled
§RegexReplace("((private|internal|public|protected)( static)?) readonly","$1")
#endif
#if !Precompiled && DEBUG
namespace NotPrecompiled
{
#endif
... // your code
#if !Precompiled && DEBUG
}
#endif
#endif // Precompiled || DEBUG
The generated source would then have:
#define Precompiled
at the top and the Generator would have executed the other required changes to the source.
During development, you could thus still have intellisense, but the release version would only have the generated code. Care should be taken to never reference the NotPrecompiled namespace anywhere.
If you are ready to ditch C# you might want to check out the Boo language which has incredibly flexible macro support through AST (Abstract Syntax Tree) manipulations. It really is great stuff if you can ditch the C# language.
For more information on Boo see these related questions:
Non-C++ languages for generative programming?
https://stackoverflow.com/questions/595593/who-is-using-boo-programming-language
Boo vs. IronPython
Good dynamic programming language for .net recommendation
What can Boo do for you?

Categories