Is there a way to get str1 in code ?
[MyAttribute("str1")]
class X {}
The instance of Mono.Cecil.CustomAttribute.Fields is empty.
When using attributes in .NET you are either using the constructor parameters and setting some (named) fields. This is encoded differently in the metadata and ends up separately in Cecil.
the instance of Mono.Cecil.CustomAttribute.Fields is empty
What you're using is looking for fields when the constructor arguments were used for the custom attribute. So what you're looking for is:
type.CustomAttributes[0].ConstructorArguments[0].Value
Related
I am trying to use CsvHelper library to write records (or list<SomeModel>) to CSV, but SomeModel class has some reference types properties that are sometimes null. I am wondering is there a way to print nulls as empty string instead of "null". I can see that CsvWriter.WriteRecords method is virtual so I can extend the class and create a custom implementation of it but there should be an easier way or some confirguration.
You can simply set this attribute
csv.Configuration.UseNewObjectForNullReferenceMembers = true;
it'll simply create a new object if a null reference is found.
In the ctor of the object class, assign empty string as default.
The optional parameters are nothing new in C# and I've known about that since the release of C# 5.0 but there is something I just came across. When I use Data Annotations for my MVC models such as the Required attribute I see this:
So I can do:
[Required(ErrorMessage="Something"]
However when I create my own methods with optional parameters like:
void Test(String x = null, String y = null) {}
I can pass arguments in both these ways:
Test(x = "Test") OR Test(x: "Test")
this while in the Required attribute I always have to use the = and if I use the : it will cause error.
for example:
Required(ErrorMessage:"Something") --> Compile time error
So what I see is that those Named Parameters are created differently than what I already knew about. And my question is How to make them for a method (How to create such Named Parameters like in the Required attribute).
An attribute has its own syntax. It uses the name=value form for named parameters.
For a normal method you can't use that form, you are stuck with the name:value form.
It would not be possible to use the name=value form for normal methods. The compiler would not be able to tell if you were trying to use a named parameter or if you were trying to assing a value to a variable and use the assignment as a parameter value.
Despite this syntax looking like a method call:
[Required(ErrorMessage="Something")]
An Attribute is a class, not a method. You aren't specifying an argument in the line above, you are initializing a property. See the example on the Attribute base class documentation to see what I mean.
The Attribute-specifying syntax is therefore similar to C#'s class initialization syntax:
new RequiredAttribute { ErrorMessage = "Something" };
There is currently no equivalent syntax in C# for specifying a named argument to a method.
If you do something like:
string y;
Test(y = "Test")
You can call a function with that syntax. But be careful... the y = "Test" is actually setting the variable y, and then passing that to the function! There is a side-effect there which is probably undesirable. Also "Test" is getting passed into parameter x of the Test function, not y because it's going in as the first parameter.
In short, you should always avoid using this syntax when calling a function, because it doesn't do what you're expecting.
I am using the SimpleMembership provider and adding additional fields to be saved on registration.
To save additional fields on registration I use the method used everywhere e.g. Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, Entity Framework 5 CodeFirst, and Custom User Properties.
I use the following SimpleMembership provider method called in my HttpPost ActionResult Register method.
WebSecurity.CreateUserAndAccount(registerModel.UserName, registerModel.Password,
new { FirstName = registerModel.FirstName, LastName = registerModel.LastName, CompanyName = registerModel.CompanyName});
Additional fields get added by a by value method parameter of type object. The description for this is "A dictionary that contains additional user attributes"
This works, but I have JetBrains ReSharper 8 installed and for the property names I get "redundant explicit property name" warnings.
To remove the warnings I changed my code to:
WebSecurity.CreateUserAndAccount(registerModel.UserName, registerModel.Password,
new { registerModel.FirstName, registerModel.LastName, registerModel.CompanyName});
My questions are:
1) for this anonymous object parameter where I now remove the property names so I don't get the Resharper warnings anymore, how does it know what the property names will be use to match to the db property class, since they are passed by value?
2) what is best practice having the property names in or not. Having them not in is not very readable and in code samples they are specified, so I would imagine having them in is better for readability rather than removing it.
My question are 1) for this anonymous object parameter where I now remove the property names so I don't get the Resharper warnings anymore, how does it know what the property names are since they are passed by value?
The names are inferred (by the compiler) from the expressions. This only works when you're using a field or property (not a literal or a method for example). This is in section 7.6.10 of the C# language specification.
2) what is best practice having the property names in or not. Having them not in is not very readable and in code samples they are specified so I would imagine having them in is better rather than removing it
If it's more readable for you and your team to always include the name, then go ahead and do so. For other people, it may feel a little redundant. Just adjust your R# settings to fit your local conventions.
Your argument that "in code samples they are specified" is specious though - there are some examples where they're specified and some where they're not. I suspect you'll find a mixture even within particular example providers (e.g. in MSDN).
When you set up your propertyNames object you're creating an instance of an anonymous Type - when you do that you can leave out the property name if it's the same as the property from which you're assigning the value. That's why ReSharper says the names are redundant.
Explicitly stating property names when you don't have to is personal preference; once you're familiar with the above convention I don't think it harms readability.
how does it know what the property names will be use to match to the db property class since they are passed by value
In a nutshell anonymous types are created on compile time. So the compiler resolves property names using expressions passed and in the result we have an anonymous class with declared readonly properties. You can check your IL in order to see that the assembly contains this type and properties are set explicitly.
what is best practice having the property names in or not
It depends on each person. I would recommend to choose a single way for your team and use the same ReSharper settings on each developer machine.
Is it possible to set attribute value [] for class or property based on machine.config field ?
Thanks for help
Not directly because attribute parameters/values have to be constant.
You can, however, write a custom attribute or inherit from the one you are working with to load the value at runtime.
No, it is not possible. Attributes are metadata that are baked into the assembly at compile time. This means that everything that you pass as values to attributes need to be constant and known at compile-time. Files such as machine.config are read at runtime.
I am trying to use Cecil to inspect the attributes associated with a given method. It seems to find it, but I cannot get its name using the following code:
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(pathBin);
assembly.MainModule.Types[0].Methods[1].CustomAttributes[0].ToString()
I know this must be the attribute I've set my function to, because when I remove it from the dll, the second line of code will turn out to null. What I'd like to do is be able to get the attribute's name. Currently the second line of code will return just a "Mono.Cecil.CustomAttribute". I'd guess there should be a way of getting an attribute's name(class type) name, right?
Thanks!
I had trouble with this when writing MoMA as well. Here is the code it uses:
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(pathBin);
assembly.MainModule.Types[0].Methods[1].CustomAttributes[0].Constructor.DeclaringType.ToString()
A CustomAttribute is an instance of a System.Attribute derived Type, so ToString() will do whatever the author decided.
If you want to know about attribute types you should ask for their type:
typeInfo.GetCustomAttributes(false)[0].GetType().ToString() ;
I haven't seen this property CustomAttributes you are using, so I rather used the method MemberInfo.GetCustomAttributes(bool) which I always use.