I am trying to clean up my code by declaring some string literals in one place instead of using them directly. For my use case, I need to access each separately, and later do something with all the values. One solution would be making a new class for each such scenario and backing the properties with a Dictionary<string, string>, but I'd like to avoid bloating the codebase.
I have a working solution using anonymous objects, whose properties are then read using reflection. But ideally, I'd like to get by without it.
var fields = new { DescriptiveName1 = "PREFIX_COL_XYZ", DescriptiveName2 = "PREFIX_THING_ABC" };
var relevantValue = originalData.GetSomeValueAs<int>(fields.DescriptiveName1);
// etc.
var keyValuesForReporting = GatherReportingData(originalData, fields);
IReadOnlyDictionary<string, string> GatherReportingData<T>(OriginalData data, T fields)
=> typeof(T) // ...
There is the ITuple interface, which would make this easy. Unfortunately, I don't have access to it on this project (required to use .NET Standard 2.0 for interoperation).
The code before my refactoring efforts looked something like this:
var relevantValue = originalData.GetSomeValueAs<int>("PREFIX_COL_XYZ");
var relevantValue = originalData.GetSomeValueAs<int>("PREFIX_THING_ABC");
// ...
var fieldsUsedInAlgorithm= new[] { "PREFIX_COL_XYZ", "PREFIX_THING_ABC" }; // notice the duplicated string literal
var keyValuesForReporting = GatherReportingData(originalData, fieldsUsedInAlgorithm);
Related
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;
}
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
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).
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));
I am not accustomed to use Var implicitly typed variable. Anyone can let me know the advantage to use such variable?
Annonymous types:
var person = new { Name = "John", Surname = "Doe" };
One thing is that it's a short hand for long types...Such as:
List<Dictionary<string, object>> myList = getList();
Can be simplified to:
var myList = getList();
Under normal use, 'var' is entirely optional and equivalent to manually specifying the type. See here.
However, the 'var' keyword is needed for anonymous types, which I've normally used in conjunction with LINQ.
I specifically find it much easier to read this:
foreach(var dbitem in context.usp_GetUserAndAccountData())
{
txtUserName.Text = dbitem.UserName;
// ...
}
Than this:
foreach(ISingleResult<usp_GetUserAndAccountDataResult> dbitem in context.usp_GetUserAndAccountData())
{
txtUserName.Text = dbitem.UserName;
// ...
}
For me, regardless of what I explicitly define dbitem, I'll still do the same actions; so var here is priceless!
And the beauty of it all is that IntelliSense will still list you all the members of the expected type on the other end (such as UserName in my example).
Better code readability. Especially used with constructors and long type name:
var anArray = new String[3];
var iStream = new InputStream(...);
var dict = new Dictionary<string, int>();
Just be mindful that using var is not always what it seems (though mostly is). An example is this:
dataList is a DataList control on a webform
foreach (var item in dataList.Items)
{
// item is of type System.Object
}
foreach (DataListItem item in dataList.Items)
{
// item is of type DataListItem
}
I believe that it was created for the purpose of anonymous types (ala Kugels example):
var person = new { Name = "John", Surname = "Doe" };
However since I discovered it I have to admit I have found it quite useful in day-to-day use when dealing with longer type names, for example:
var aaa = new Dictionary<string, List<ReallyLongTypeName>>();
// vs
Dictionary<string, List<ReallyLongTypeName>> aaa = new Dictionary<string, List<ReallyLongTypeName>>();
Another side effect is that type names can change (or be replaced with other types), but code that uses var wont' break, for example:
var item = this.GetItem();
this.Name = item.Name;
this.Age = item.Age;
As long as the return value from GetItem always has a property Name and a property Age (which are compatible with the properties on this) then GetItems can return an entirely different object and the above code will still compile. (But be careful - existing compiled assemblies can't use the same trick!)
Apart from the other answers, to me a real advantage is when dealing with external code, to decouple the variable type from the actual method signature.
Consider this interface:
public interface IFoo
{
List<Foo> GetSomething();
}
And say you have two lines of code:
List<Foo> foos = fooRepo.GetSomething();
var foos2 = fooRepo.GetSomething();
Same result for above two lines. (List<Foo> returned).
Now if changed the interface:
public interface IFoo
{
Dictionary<bool,Foo> GetSomething();
}
The first line would now throw a compiler error, the second would not:
List<Foo> foos = fooRepo.GetSomething(); // error - can't convert from Dictionary<bool,Foo> to List<Foo>
var foos2 = fooRepo.GetSomething(); // works!
This is really handy when working with repositories/other projects where interface contracts/method signatures can change.
Yes you still have to recompile the classes, but you don't have to go back and change all the code that referenced the old return type.