Can roslyn generate enums? - c#

So, I feel like it's possible, but i don't have the chops to put it together. I have lookup tables (with ID and Name fields). I have enums that I keep in sync with the lookups. What I'd like is to make a list of SQL tables, and have roslyn create the enums during/before compile. this way I know my enums are always in sync, and it's one more thing off my plate.
Could someone out there show me the way, or tell me why it would be a bad idea? I feel like the solution isn't really a lot of code...
Thanks!

This is how you create enums with roslyn;
class Program
{
static void Main(string[] args)
{
var member1 = Syntax.EnumMemberDeclaration(
identifier: Syntax.Identifier("Member1")
);
var declaration = Syntax.EnumDeclaration(
identifier: Syntax.Identifier("MyEnum"),
modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)),
members: Syntax.SeparatedList(member1)
);
Console.WriteLine(declaration.Format());
Console.ReadLine();
}
}
this returns:
public enum MyEnum
{
Member1
}
Now to your question, I don't know if this is what you really need.
First I think there is not yet any built in functionality to do this at precompile, so you'd need to create a console exe and call it in your prebuild events.
So at this point probably it is a better idea to do this manually via code generation and not on every build, unless these tables are changing very frequently.
An in this case you don't really need roslyn to do it for you, you can just spit it out with any code generation software, or roll your own...

Here is some code updated for the current version of Roslyn and also shows adding attributes and values to the enum items.
public EnumDeclarationSyntax GenerateEnum()
{
var loanPurpose = new[]
{
"Business Launching",
"HomePurchase",
"HomeImprovement"
};
var enumDescriptions = new[]
{
"Launch a new business",
"Buy a home",
"Make home improvements"
};
var i = 0;
var members = new List<EnumMemberDeclarationSyntax>();
foreach (var item in loanPurpose)
{
var attribute = SyntaxFactory.Attribute(
SyntaxFactory.IdentifierName("Description"));
var attributeArgument = SyntaxFactory.AttributeArgument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(enumDescriptions[i ])));
attribute = attribute.WithArgumentList(
SyntaxFactory.AttributeArgumentList(
SyntaxFactory.SingletonSeparatedList(attributeArgument)));
var attributes = SyntaxFactory.SingletonList(
SyntaxFactory.AttributeList(SyntaxFactory
.SingletonSeparatedList(attribute)));
var objectCreationExpression = SyntaxFactory.EqualsValueClause(
SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression,
SyntaxFactory.Literal(i)));
var member = SyntaxFactory.EnumMemberDeclaration(attributes,
SyntaxFactory.Identifier(item),
objectCreationExpression);
members.Add(member);
i++;
}
var declaration = SyntaxFactory.EnumDeclaration
(new SyntaxList<AttributeListSyntax>(),
baseList: null,
identifier: SyntaxFactory.Identifier("LoanPurpose"),
modifiers: SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)),
members: SyntaxFactory.SeparatedList(members)
);
return declaration;
}
The syntax for adding the attributes gets a little awkward but I find that I often need some attributes added. You probably already have the data for the attributes and values in the lookup tables driving the code generation.

The Answer provided by Sebastian 6 years ago likely used to work but no longer does.
New set of sample code to accomplish the same thing as of 18/12/2017
EnumMemberDeclarationSyntax member1 = EnumMemberDeclaration(identifier: Identifier("Member1"));
var members =new SyntaxNodeOrToken[]{member1};
var declaration = EnumDeclaration(
identifier: Identifier("MyEnum")).WithMembers(
members: SeparatedList< EnumMemberDeclarationSyntax>(members));

Related

Detect access to data from a method in c#

I have a method and I want to find all data accessed inside this method.
for example:
public class foo
{
private int field;
public void method()
{
field = 0;
}
}
I need a way to know (from the source code or the assembly) that 'field' is accessed within 'method'.
Note: I already used Harmony Library (https://github.com/pardeike/Harmony) to find all the calls to methods inside a specific method. It would be amazing if someone knows how to use it to also find data accessed.
as pointed out in comments, Roslyn DataFlowAnalysis is probably the best tool for the job:
SyntaxTree tree = CSharpSyntaxTree.ParseText(
#"public class foo
{
private int field;
public void method()
{
field = 0;
}
}");
var compilation = CSharpCompilation.Create("test").AddSyntaxTrees(tree).AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
var model = compilation.GetSemanticModel(tree);
var methodDeclaration = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
var dataFlow = model.AnalyzeDataFlow(methodDeclaration.Body);
foreach (var symbol in dataFlow.DataFlowsIn)
{
Console.WriteLine(symbol.Name, symbol.Kind);
}
analysis for your particular example yields reference to class foo through implicit
this, but not the field itself (which is technically correct but not very helpful). Assuming your actual code will likely have a bit more dependencies in it - you may see better results.
If you look at the list of opcodes in IL you find that you want to search for OpCodes.Ldfld and OpCodes.Ldflda. Harmony’s CodeInstruction has two fields to use: compare code to either opcode and use operand and cast it to a FieldInfo to learn about what field is read. Use OpCodes.Stfld(a) for write access to fields.

C#, Generics, Type and NHibernate

I'm learning the power of generics in C# in conjunction with NHibernate. I'd like to attempt the following in the pasted code.
In an attempt to do some post processing of N number of NHibernate objects I worked on a utility method leveraging generics to make it applicable to all NHibernate mapping classes we use now, or in the future. It works but I need to hard code each call for each mapping class. This is a pain and will need continuing updating as our schema and mappings change over time.
I do have an ever up-to-date list of all mapping classes by string name through the NHibernate mappings I generate on the fly. If there was a way to use this list of string names to call my generics based method, I'd be super happy.
Can anyone tell me if this is possible? Do I need to find another route?
Thanks so much in advance!!!
public static void ProcessSomeItems()
{
// *************************************************************
// As of now I have to list all classes as such to be processed
// It works but I have to update manually when new mapping classes are created
// *************************************************************
NHibDoSomethingUtil<AspnetMembership>();
NHibDoSomethingUtil<AspnetProfile>();
NHibDoSomethingUtil<AspnetRole>();
NHibDoSomethingUtil<AspnetUser>();
// and so forth...
// I have a up-to-date list of all mappings from "HbmMapping" and can get a list of all in the
// list form as below
List<string> mappingNames = new List<string>();
foreach (string mappingName in mappingNames)
{
Type theType = Type.GetType(mappingName);
// I know I'm getting Types and Generics classes and so forth all jumbled but
// how in the heck would I do something like the below?
NHibDoSomethingUtil<theType>(); // Obviously doesn't compile ;-)
}
}
// Generic method
public static void NHibDoSomethingUtil<T>() where T : class
{
using (ISession session = sourceDBSessionFactory.OpenSession())
{
foreach (dynamic item in new List<T>(session.QueryOver<T>().List()))
{
// Process item;
}
}
}
ecsousa gave great input and I was able to accomplish what I needed with something like the following.
foreach (HbmClass mappingClass in mapping.Items)
{
Console.WriteLine(" -- Discovered Mapping: " + mappingClass.Name);
Type mappingClassType = Type.GetType(mappingClass.Name);
var genericMethod = typeof(Migration).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(mappingClassType);
method.Invoke(null, null);
}
You will need to use Reflection in order to accomplish this. Instead of directly calling NHibDoSomethingUtil, try this:
var genericMethod = typeof(TheClassName).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(theType);
method.Invoke(null, null);
Note that you have to replace TheClassName by the class containing both methods.
Keep in mind the this kind of code is slow, and you should use it very carefully.

NancyFx DynamicDictionary

I am trying to understand the DynamicDictionary in NancyFX, it looks pretty cool. Does anyone know of a blog post or similar, that goes through the internals of it?
I need a propertybag to pass around objects, that I don't know the content of because they come from outside my system as JSON. But based on the contents of these objects, such as the presence of certain properties I need to do stuff.
I could just pass around dynamic objects, but that is a bit too vague I think. Don't really like that.
I would need nested dictionaries, to fully represent the object graph.
The dynamic dictionary is just a ExpandoObject with a Dictionary in it. So it can still be accessed like a dictionary.
For example, in MVC you access Form properties like so:
var name = Request["name"];
or
var name = Request.Form["name"];
When a request comes into Nancy you can access it via the dot notation. Or via the class indexer.
var name = parameters.name;
var name = parameters["name"];
This is handy when you're sending query string or form names that have values that cannot be used in dot notation.
var firstName = parameters["first-name"];
The values are also dynamic, so it could be made up of nested objects. This allows you to do stuff like:
var firstName = parameters.contact.firstname;
So if you're passing a JSON payload to the request then you can access the entire structure using dot notation.
However you will probably find most developers using Nancy only ever access Route values or QueryString values using this method.
Get["/products/{id:int}/"] = parameters => {
int id = parameters.id;
};
So back to the original question:
Is there a blog post or any doco: Nope.
Why does it exist: For sugar syntax.
Can I use it for what I want: Yes absolutely!
Can you tell me how to use it: Nope, however it shouldn't be hard. Just look the model binding in Nancy to figure it out. It's not too hard.
Just an edit based on the answer by the OP.
When you access the dot notation, continued dot notation will only work on further dynamic types.
This means using var will cause an exception because of the way var and dynamic are handled by the compiler.
When you do:
var person = parameters.person;
var name = person.name;
parameters is currently dynamic and implements TryGetMember, this internally looks up a dictionary of values and attempts to return the value.
When you define the object as var for the person variable. The compiler assumes that anything after that exists on the object, so it looks for name on the person variable.
Since name does not exist as a member of person it will throw.
To resolve this, the variable must be assigned as dynamic. So the example becomes:
dynamic person = parameters.person;
var name = person.name;
This will work.
So I started working with the DynamicDictionary and it is pretty cool and easy to work with. Only one thing bugs me right now. That is if I nest DynamicDictionaries.
Look at the following example:
private void TestNestedDynamicDictionary()
{
dynamic dictionary = new DynamicDictionary();
dynamic nestedDictionary = new DynamicDictionary();
nestedDictionary.Add("name", "Peter");
dictionary.Add("person", nestedDictionary);
var person = dictionary.person;
var name = person.name;
Console.WriteLine(name);
}
This fails when trying to access person.name with a 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
DynamicDictionaryValue' does not contain a definition for 'name'
If I just do an explicit cast like this it works.
var person = (DynamicDictionary)dictionary.person;
Any input on how I could make it behave as DynamicDictionary right out of the box... apart from checking the DynamicDictionaryValue before it is returned, and do the cast there, which I think is messy.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (!dictionary.TryGetValue(binder.Name, out value))
{
result = new DynamicDictionaryValue(null);
return true;
}
var dictVal = value as DynamicDictionaryValue;
if (null != dictVal && dictVal.Value is DynamicDictionary)
{
result = dictVal.Value;
}
else
{
result = value;
}
return true;
}

Dynamically find used properties prior to them being used

I am looking for optimization of a pattern I am using for a dynamic forms application.
I have a repository class with a method:
public Entity Find(string objectId, List<string> includedProperties);
This returns an Entity object, with only the fields specified in the "includedProperties", as building the entire object for all purposes is unnecessary overhead in this case (some entities have hundreds of properties).
Example domain code using this repository often looks something like this:
var includedProperties = new List<string> {
"FirstChildName" ,
"FirstChildDob",
"SecondChildName",
"SecondChildDob"
}
I then fetch an object:
var person = repository.Find("123",includedProperties);
I then use the Properties with a GetProperty(string propertyName) method:
var firstChildDob = person.GetProperty("FirstChildDob").AsDateTime();
...etc
This all works fine, and fits well with the dynamic design of the application. However, I find it irritating that I always need to declare a list of "used" properties separately, prior to fetching the object.
So, my question is, through reflection or some other cleverness, can I simplify the building of the "Included Properties" by looking at which parameters get passed later in the code with the "GetProperty" method?
Using the above example, I'd like to build the list using a helper like this (or similar):
var includedProperties = HelperObject.GetFieldsUsedInCurrentCodeFile();
This would somehow pickup what string constants were passed to the "GetProperty()" method, saving the need for explicit declaration. Any suggestions welcome!
I actually had a similar problem awhile back; the best I could come up with at the time was to define an enum that contained the names of the properties I wanted to use in the method.
Using this approach, you could build the list of included properties by cycling through the enum.
There are a couple of benefits to this approach vs. strings:
Any property spelling issues or property name changes are made in a single location.
If you are using a tool such as Resharper, you can determine when you have unused "properties" in the enum.
For example:
private enum PersonMethodProperties
{
FirstChildName,
FirstChildDob,
SecondChildName,
SecondChildDob
}
private void PersonMethod()
{
var includedProperties = GetIncludePropertiesFromEnum(typeof(PersonMethodProperties));
var person = repository.Find("123", includedProperties);
var firstChildDob = person.GetProperty(PersonMethodProperties.FirstChildDob.ToString()).AsDateTime();
}
private List<string> GetIncludePropertiesFromEnum(Type propertiesEnumType)
{
var includedProperties = new List<string>();
foreach (var name in Enum.GetNames(propertiesEnumType))
{
includedProperties.Add(name);
}
return includedProperties;
}
Code analysis tools like Nitriq or NDepend unfortunately won't help you because in current version they do not capture method's arguments names and values.
But you can use Roslyn to create tool that will analyze your solution and generate a class containing list with used properties as a pre-build event. Code for solution analysis that finds all calls to className.methodName and returns its constant arguments (text in your case):
static IEnumerable<string> GetMethodCallParametersValues(string solutionName,
string className,
string methodName)
{
var workspace = Workspace.LoadSolution(solutionName);
var solution = workspace.CurrentSolution;
var createCommandList = new List<ISymbol>();
var #class = solution.Projects.Select(s => s.GetCompilation()
.GetTypeByMetadataName(className))
.FirstOrDefault();
var method = #class.GetMembers(methodName)
.AsList()
.Where(s => s.Kind == CommonSymbolKind.Method)
.FirstOrDefault();
var locations = method.FindReferences(solution)
.SelectMany(r => r.Locations);
List<string> result = new List<string>();
foreach (var location in locations)
{
var model = location.Document.GetSemanticModel();
var token = location.Location
.SourceTree
.GetRoot()
.FindToken(location.Location.SourceSpan.Start);
var invocation = token.Parent.FirstAncestorOrSelf<InvocationExpressionSyntax>();
var arguments = invocation.ArgumentList.Arguments;
result.AddRange(arguments.Select(a => model.GetConstantValue(a.Expression).Value.ToString()));
}
return result.Distinct();
}
and code usage:
var includedProperties = GetMethodCallParametersValues(#"c:\path\to\your.sln",
"SomeNamespace.SomeClass",
"GetProperty");
Note: Because of Roslyn's small bug in parsing Solution file, you probably will have to comment below lines in .sln file by adding # so they will look:
# VisualStudioVersion = 12.0.21005.1
# MinimumVisualStudioVersion = 10.0.40219.1

Roslyn CTP - Random Code Modification

I have been experimenting with the Roslyn API in a genetic programming type of scenario. It appears like a great way to do that type of programming, but the actual implementation of simple scenarios doesn't seem very straightforward, which means I probably don't have a good understanding of how to use this API properly. Here is a simple program I am trying to modify in my experiments:
string treeText = #"using System;
using System.Collections.Generic;
namespace TestProgram
{
class Program
{
static void Main(string[] args)
{
var myVar = 3;
string myString = ""Hello World"";
List<string> stringList = new List<string>();
Console.WriteLine(myString + myVar);
Console.ReadLine();
}
}
}";
SyntaxTree tree = SyntaxTree.ParseText(treeText);
var compilation = Compilation.Create("test.exe",
syntaxTrees: new[] { tree },
references: new[]
{
new MetadataFileReference(typeof(object).Assembly.Location),
new MetadataFileReference(typeof(Enumerable).Assembly.Location),
});
SemanticModel model = compilation.GetSemanticModel(tree);
Just as a simple example let's say I somehow "randomly" decided I want to insert a new method invocation using the myString instance. What would be an efficient way to figure out what methods I could invoke off of that instance? What would then be the best way to create the necessary MethodInvocationSyntax (once I chose a specific method to use) from the symbol information? I found a method called ResolveOverloads on the SemanticModel class which appears where I need to end up, but I am having some difficulty figuring out an efficient path to the parameters this method requires. Is that even the right path to go down?
First, get the VariableDeclaratorSyntax for your variable, for example:
var variable = tree.GetRoot().DescendantNodes()
.OfType<VariableDeclaratorSyntax>()
.Single(v => v.Identifier.ValueText == "myString");
Next, get the LocalSymbol for this variable from the SemanticModel:
var variableSymbol = (LocalSymbol)model.GetDeclaredSymbol(variable);
Then you can get a list of methods you can invoke on this variable based on its type. You can either simply get all members of the type that are instance methods:
var methods =
variableSymbol.Type.GetMembers()
.OfType<MethodSymbol>()
.Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary);
Or, if you wanted to include extension methods, you could use LookupSymbols():
var methods = model.LookupSymbols(
variable.GetLocation().SourceSpan.Start, variableSymbol.Type,
options: LookupOptions.IncludeExtensionMethods)
.Where(m => !m.IsStatic);
You can then choose one of the available methods based on your logic and create InvocationExpressionSyntax (the following code assumes it's a parameterless method):
var invocationExpression =
Syntax.InvocationExpression(
Syntax.MemberAccessExpression(
SyntaxKind.MemberAccessExpression,
Syntax.IdentifierName(variableSymbol.Name),
(SimpleNameSyntax)Syntax.ParseName(selectedMethod.Name)));
You would then need to figure out where in your method to add the expression and what to do with its result (if anything).

Categories